#include <iostream> #include <vector> #include <algorithm> using namespace std; void quickSort(vector<int> &vec,int l,int u){ int i , m; if( l>=u) return ; m = l; for(i = l+1; i <= u; i++){ if(vec[i] < vec[l]){ ++m; swap(vec[m],vec[i]); } } swap(vec[m],vec[l]); quickSort(vec,l,m-1); quickSort(vec,m+1,u); } void printInfo(vector<int> vec){ vector<int>::iterator it = vec.begin(); for(; it != vec.end(); it++) cout << *it << " "; cout << endl; } int main(){ vector<int> vec; for(int i = 1; i <= 100; i++) vec.push_back(i); cout << "----------before shuffle-----------" << endl; printInfo(vec); random_shuffle(vec.begin(),vec.end()); cout << "----------after shuffle-----------" << endl; printInfo(vec); quickSort(vec,0,99); cout << "----------after quickSort-----------" << endl; printInfo(vec); getchar(); return 0; }
结果:
-----------------------------------------------------------------------------------------------------------------------------------------
在排序中,有几种比较重要的排序。快速排序,堆排序,归并排序。
查找中比较重要的哈希查找(因为时间复杂度是0(1)),二分查找(O(logn))。
上一次写的快速排序的博客是根据严蔚敏老师的教材来写的,现在觉得有点不平易近人,晦涩难懂。
今天就重新来整理一下快速排序,希望自己能够做到对快排信手拈来,熟记于心。大不了,背下来也可以。
1 void quicksort(int l, int u){ 2 int i, m; 3 if(l >= u) return; 4 m = l; 5 for(i = l+1; i<= u; i++) 6 if(x[i] < x[l]) 7 swap(++m, i); 8 9 swap(l, m); 10 11 quicksort(l, m-1); 12 quicksort(m+1, u); 13 14 }
这是Jon Bently在beautiful code里的代码。
最核心的代码就是for循环那一块了,在for循环之后,[ l + 1, m ]里全是比pivot小的数(pivot是x[l]),然后通过swap(l,m)将下标为m和l的数字交换。
这样就完成了一边partition,下标m之前的数全都小于pivot,下标m之后的数全都大于pivot。
但是有一个Bug。当存在很多与pivot相等的数时,这些数会整体被分在m的左边或者m的右边。
如果我们想在一个partition中分成三部分,即左边部分是小于pivot,中间等于pivot,右边全都大于pivot。然后在下一次partition的时候只对左右两部分调用。
private static void sort(Comparable[] a, int lo, int hi) { if (hi <= lo) return; int lt = lo, gt = hi; Comparable v = a[lo]; int i = lo; while (i <= gt) { int cmp = a[i].compareTo(v); if (cmp < 0) exch(a, lt++, i++); else if (cmp > 0) exch(a, i, gt--); else i++; } // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]. sort(a, lo, lt-1); sort(a, gt+1, hi); assert isSorted(a, lo, hi); }
上面代码使用三个指针 lt gt i (less than , greater than)
其中 lt 指向的是比pivot小的那些数的下一个坐标, gt 指向的是比pivot大的那些数的上一个坐标。中间的就是跟pivot一样大的数了。
如若还不熟,建议用张纸,多画一画就好。