关于快排的细节

 关于快排的主体思想那自然不用说,但是具体代码实现的细节确是很多。下面通过网上找的多个版本来找找其中的细节与优劣。相信只要你对这块不是十分了解或者自己仔细琢磨过细节,那么阅读本文肯定有所收获。

转载请注明,原文来自https://www.cnblogs.com/willhua/p/9426130.html

版本1
public static void quickSort(int[] a, int start, int end) {         if (start >= end)   return;         int t = a[end];         int i = start - 1;          for (int j = start; j <= end - 1; j++) {             if (a[j] < t) {                 i++;                 swap(a, i, j);             }         }         swap(a, i + 1, end);         quickSort(a, start, i);         quickSort(a, i+2, end);     } //来源:https://www.zhihu.com/question/24361443/answer/362777698

分析:这个的特点在于从一头遍历到尾来进行二分,而不像一般的从两头分别开始。对于核心的for循环,首先分析其if,它是当当前处理的元素如果小于t,那么就进行swap,如果大于或者等于t则不会进行交换,这样的话,i就不会增长,也就意味着i表示的是第一个大于或等于t的元素所在的位置,即意味着(i, j)都是属于大于或者等于t的元素。后续处理中,如果if条件满足,那就相当于把第一个大于或者等于t的元素放到当前小于t的位置,同时把这个小于t的元素放到前面的小于t范围的末位,形成了大于或者等于t的范围的翻滚式的向后面移动或者前进的效果。
这种写法从语言的简洁上来说是比从两头分别处理的版本的好,但是这种写法会比两头处理的版本更多次的swap,尤其考虑在数组的前面某个范围,其数据本身都是小于t的,那么使用这种版本也会进行很多次swap,即这些swap也根本就没有改变数组的任何排列,或者带来任何变化。

版本2:有bug
void quick_sort(vector<int> &a,int l,int r) {    if(l<r)    {        int po=a[l];        int ll=l,rr=r+1;        for(; ;)        {            while(a[++ll]<po);            while(a[--rr]>po);            if(ll>rr)                break;            else                swap1(a[ll],a[rr]);        }        swap1(a[l],a[rr]);        quick_sort(a,l,rr);        quick_sort(a,rr+1,r);    } } //来源:https://www.zhihu.com/question/24361443/answer/362777698

分析:这个版本也是参考的《数据结构与算法分析c++描述》,但改写不成功,有两个明显的bug:

  • bug1:如果输入的数组a的第一个位置的元素是整个数组的最大值,那么,在while(a[++ll]<po);这句中,因为所有的元素都满足while条件,那么ll必定会执行到数组的最后一位,直至越界报错。
  • bug2:如果输入数组的第一个位置是整个数组的最小值,那么第二个while循环就会出现bug1同样的错误,rr会一直往前走,直至越界报错。

其实,这个bug,在网上很多版本中都存在这样的问题。所以,在《数据结构与算法分析 c语言描述》中特意分析了哨兵设置或者边界处理的细节。

版本3

template <typename T> void quick_sort_recursive(T arr[], int start, 
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信