快速排序
快速排序:
什么是快速排序呢,其实快速排序就是选择一个数出来(比如说第一个数),然后后面的数依次跟这个数比较,比它小的就放前面,比它大的就放后面。
比较好想,但是比较耗费空间的是利用多一个数组。
但是有没有比这种方法好的呢?有的,不需要一个额外的数组,通过两个指针就可以了。
这样一次排序好之后,再用5左右两边的数运用同样方法排序一次。
简而言之,就是左边有空的,就从右边找一个小的数过来补充。
右边有空的,就从左边找一个大的数过来补充。
代码:
void sort(int num[],int begin ,int end)
{
if(end<begin)return;
int privoty=num[begin];
int leftkey=begin;
int rightkey=end;
while (leftkey <rightkey) {
while (num[rightkey] > privoty && rightkey > leftkey) {
rightkey--;
}
if(leftkey<rightkey) {
num[leftkey] = num[rightkey];
leftkey++;
}
while (num[leftkey] < privoty && rightkey > leftkey) {
leftkey++;
}
if(leftkey<rightkey) {
num[rightkey] = num[leftkey];
rightkey--;
}
}
num[leftkey] = privoty;
sort(num, begin, leftkey - 1);
sort(num, rightkey + 1, end);
}
代码方面不难写出来,但是有很多需要注意的点,很多小细节来着。
首先,按照思路还是不难写出一个while循环再接上下面的实现。
细节1
一开始第一个错误是,在while循环内的判断都用if,这样肯定是不行的,因为我们要实现的是在一个循环内,让指针有多此移动的机会。如果写成if的话,那么一个循环内就判断一次,一个指针也只能移动一次。
所以里面两个都得套一个while循环。
细节2
内while循环条件只写了一个,原本以为内while循环条件就只写num[rightkey] > privoty就好,不需要写 rightkey > leftkey,因为外面已经套了一个大的while循环,条件就是rightkey > leftkey了。
这里就是误区所在。其实,如果内循环没写rightkey > leftkey的条件,如果已经破话了这个条件,外循环是不会感受到,不会停止的。
为什么呢?因为对于外循环来说,它的判断是每次循环体内的语句执行完成之后再做判断。而不是实时做判断,所以在内循环内也必须写上rightkey > leftkey的条件,以防它在内循环移动的过程中都已经越界了。
细节3
为了使每次结束的时候都是rightkey==leftkey,最好就写多一个
if(leftkey<rightkey) {
num[leftkey] = num[rightkey];
leftkey++;
}
判断一下,此时就是leftkey==rightkey了。
也因此,下面的递归
sort(num, begin, leftkey - 1);
sort(num, leftkey + 1, end);
就都可以用leftkey表示。
但是如果没有写判断条件的话,leftkey和rightkey是不一样的,所以就必须区分
sort(num, begin, leftkey - 1);
sort(num, rightkey + 1, end);
所以无论哪种情况,反正都写区分的一种就好啦,就不会错!
细节4
就是结束递归的条件,这个不好想,一开始是觉得begin==end的时候,就结束。
但是其实刚说了,leftkey指针和你想的不一样,有时候并不相等,但也得结束,就是小于的时候,所以在快速排序中,更常用的不是说两个不相等的时候结束,而是一个小于另一个的时候结束。 记住就好。
所以总结一下快速排序代码的要点:
- 分治实现,不用合并
- while大循环和里面while小循环,都得有rightkey > leftkey的条件
- 结束递归的条件是end<begin
- 最好区分leftkey和rightkey
- 无了