转:快速排序的一个小问题没想明白,求助各位
2014-09-17 22:20
661 查看
转自:http://bbs.csdn.net/topics/390797415
提问如下:
我开始写的时候是先i++后j--,但是这样出来的结果不对,而先j--后i++就没问题,结果是对的,但是我不明白是为啥,谁能给说一下,谢谢
回答:
(题外话:代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。提醒:再牛×的老师也无法代替学生自己领悟和上厕所!单步调试和设断点调试是程序员必须掌握的技能之一。)
支点是 a[left],即左边第一个数。
最终结果是:i左边的都比支点小,右边的比它大。
1.先--j,后++i,则因为++i 时保证了i<j,故如果j<=i 时,i不再变动。
2.反之,先++i,则可能因为if(i < j)不成立,于是下面交换不执行,导致 i 并不满足最终结果。
eg: 4 8 1 5 7
1. a). temp = 4, j = 2, i = 1, a[i] = 8, a[j] = 1; -> 4 1 8 5 7
b). j = 1, i = 1; ->结束
2. a). i = 1, j =2, a[i] = 8, a[j] = 1; -> 4 1 8 5 7
b). i = 2, j = 2; ->结束 这样交换的支点就不对了(8)
总结:之前我好像也犯过这个错误。修正后的代码如下。
.....
.....
一道题目参考参考:(转自:http://bbs.csdn.net/topics/340111907)
以下是2008自考的一个选择题,请高手们看一下,这个题应选什么呢?
对下列关键字序列进行快速排序时,所需进行比较次数最少的是( )
A.(1,2,3,4,5,6,7,8) B.(8,7,6,5,4,3,2,1)
C.(4,3,8,6,1,7,5,2) D.(2,1,5,4,3,6,7,8)
superdullwolf:
partition一般不是选第一个元素就是最后一个元素,选到中位数的时候速度最快。因为第一次就把牌一分为二了。
根据题目,最大数字是8,应该是选到4的时候最快,那肯定老师教的就是把第一个元素作为关键字了。所以是C。其实对于有限范围内整数,密集不重复数字的排序,最快的是计数排序,O(n),而且代码和理论都超级简单。象这个题目这样就是。(计数排序:http://www.cnblogs.com/kaituorensheng/archive/2013/02/23/2923877.html)
tu_lq:
A 7+6+5+4+3+2+1=28
B 同A 28
C 7+(2+3)+1=13
D 7+6+(2+1)+1=17
选C
superdullwolf:
To:tu_lq计数排序,不是基数排序,好比你们班级有30个人考试,你准备100个桶,把分数丢到相应的桶里,再顺次拿出来,需要耗费100个空间,但是30的时间。如果只有50个桶也可以做到,桶里再摆放一下左右就可以了。
快速排序的道理,其实很好理解,只是很多书上给说迷糊了。
拿扑克来说,就是找边上的一张牌,根据这个牌,把扑克分成大小两堆,一堆都比这个小,一堆都比这个大。
所有n*logn的排序都是消耗T(n)的时间把牌分成两堆。两堆越均衡速度越快,所以每次都是中位数的话,效果最理想。
因为牌的数量在折半减少,所以T(n)=T(n/2)+n
最后是n*logn
提问如下:
void QuickSort(int a[],int left,int right) { if(left > right) return ; int i = left, j = right, temp = a[left]; while(i != j) { while(i < j && a[j] >= temp) j--; //注意这两个while while(i < j && a[i] <= temp) i++; //注意这两个while if(i < j) { int t = a[i]; a[i] = a[j]; a[j] = t; } } a[left] = a[i]; a[i] = temp; QuickSort(a,left,i-1); QuickSort(a,i+1,right); }
我开始写的时候是先i++后j--,但是这样出来的结果不对,而先j--后i++就没问题,结果是对的,但是我不明白是为啥,谁能给说一下,谢谢
回答:
(题外话:代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。提醒:再牛×的老师也无法代替学生自己领悟和上厕所!单步调试和设断点调试是程序员必须掌握的技能之一。)
支点是 a[left],即左边第一个数。
最终结果是:i左边的都比支点小,右边的比它大。
1.先--j,后++i,则因为++i 时保证了i<j,故如果j<=i 时,i不再变动。
2.反之,先++i,则可能因为if(i < j)不成立,于是下面交换不执行,导致 i 并不满足最终结果。
eg: 4 8 1 5 7
1. a). temp = 4, j = 2, i = 1, a[i] = 8, a[j] = 1; -> 4 1 8 5 7
b). j = 1, i = 1; ->结束
2. a). i = 1, j =2, a[i] = 8, a[j] = 1; -> 4 1 8 5 7
b). i = 2, j = 2; ->结束 这样交换的支点就不对了(8)
总结:之前我好像也犯过这个错误。修正后的代码如下。
.....
#include "stdafx.h" #include <iostream> void Swap(int &a, int &b) { int temp = a; a = b; b = temp; } int Partition(int a[], int l, int r) { int i = l, j = r, pivot = a[l]; while(i < j) { while(i < j && a[j] >= pivot) --j; while(i < j && a[i] <= pivot) ++i; Swap(a[i], a[j]); } Swap(a[l], a[i]); return i; } void QuickSort(int a[], int l, int r) { if(l >= r) return; int s = Partition(a, l, r); QuickSort(a, l, s - 1); QuickSort(a, s + 1, r); } void QuickSort2(int a[],int left,int right) { if(left >= right) return ; int i = left, j = right, pivot = a[left]; while(i != j) { while(i < j && a[j] >= pivot) j--; //注意这两个while while(i < j && a[i] <= pivot) i++; //注意这两个while Swap(a[i], a[j]); } Swap(a[left], a[i]); QuickSort2(a,left,i-1); QuickSort2(a,i+1,right); } int _tmain(int argc, _TCHAR* argv[]) { int a[] = {4,8,3,7,1,5,6,2}; QuickSort(a, 0, sizeof(a)/sizeof(int) - 1); int b[] = {5,3,1,9,8,2,4,7}; QuickSort(b, 0, sizeof(b)/sizeof(int) - 1); int c[] = {4,8,3,7,1,5,6,2}; QuickSort2(c, 0, sizeof(c)/sizeof(int) - 1); int d[] = {5,3,1,9,8,2,4,7}; QuickSort2(d, 0, sizeof(d)/sizeof(int) - 1); int e[] = {4,8,1,5,7}; /*QuickSort(e, 0, sizeof(e)/sizeof(int) - 1);*/ QuickSort2(e, 0, sizeof(e)/sizeof(int) - 1); system("pause"); return 0; }
.....
一道题目参考参考:(转自:http://bbs.csdn.net/topics/340111907)
以下是2008自考的一个选择题,请高手们看一下,这个题应选什么呢?
对下列关键字序列进行快速排序时,所需进行比较次数最少的是( )
A.(1,2,3,4,5,6,7,8) B.(8,7,6,5,4,3,2,1)
C.(4,3,8,6,1,7,5,2) D.(2,1,5,4,3,6,7,8)
superdullwolf:
partition一般不是选第一个元素就是最后一个元素,选到中位数的时候速度最快。因为第一次就把牌一分为二了。
根据题目,最大数字是8,应该是选到4的时候最快,那肯定老师教的就是把第一个元素作为关键字了。所以是C。其实对于有限范围内整数,密集不重复数字的排序,最快的是计数排序,O(n),而且代码和理论都超级简单。象这个题目这样就是。(计数排序:http://www.cnblogs.com/kaituorensheng/archive/2013/02/23/2923877.html)
tu_lq:
A 7+6+5+4+3+2+1=28
B 同A 28
C 7+(2+3)+1=13
D 7+6+(2+1)+1=17
选C
superdullwolf:
To:tu_lq计数排序,不是基数排序,好比你们班级有30个人考试,你准备100个桶,把分数丢到相应的桶里,再顺次拿出来,需要耗费100个空间,但是30的时间。如果只有50个桶也可以做到,桶里再摆放一下左右就可以了。
快速排序的道理,其实很好理解,只是很多书上给说迷糊了。
拿扑克来说,就是找边上的一张牌,根据这个牌,把扑克分成大小两堆,一堆都比这个小,一堆都比这个大。
所有n*logn的排序都是消耗T(n)的时间把牌分成两堆。两堆越均衡速度越快,所以每次都是中位数的话,效果最理想。
因为牌的数量在折半减少,所以T(n)=T(n/2)+n
最后是n*logn
相关文章推荐
- 请教各位高手一个问题?
- 工作当中日期排序的一个问题
- 求助一个Ajax问题
- Ihttpmodule 的一个小问题,今天明白了
- 用DataTable.Merge()解决了一个排序问题
- 关于测试一个windows动态链接库的问题;请教各位大侠!
- 请教各位大虾一个问题:联接错误怎么改啊?
- 一个急切解决的xml中的初级的初级问题,请各位同仁帮帮忙,谢谢
- 大道至简--明白了一个地球人都明白的问题。
- 整明白一个问题需要耗费这么多时间?
- 向各位请教一个关于Decorator模式的问题
- 请教各位大侠一个问题关于水晶报表的,欢迎进来讨论
- 请教各位C/VC高手一个极其郁闷的问题
- 求助:一个很奇怪的问题
- 对不起,各位哥哥,我有一个问题向你们请教,请多多指教关于C#DataGrid的问题,特急!!!
- 请各位高手看一下.这是一个关于定义冲突的问题.我应该怎么解决.急,忘各位高手指点!
- 一个关于nvarchar字段排序,中英文混合排序的问题
- 使用VS2005 CTP July调试WinForm的一个问题,解决方法与各位分享。
- 请教各位一个存储问题
- 今天好像突然想明白了一个问题