快速排序:
時間復雜度O(N*logN),最壞情況為O(N^2)
空間復雜度O(1)
但是堆棧深度一般情況為O(logN),最壞情況為O(N)
快速排序實現:
partition划分算法:
int Partition(SeqList R,int i,int j) { //調用Partition(R,low,high)時,對R[low..high]做划分, //並返回基准記錄的位置 ReceType pivot=R[i]; //用區間的第1個記錄作為基准 ' while(i<j){ //從區間兩端交替向中間掃描,直至i=j為止 while(i<j&&R[j].key>=pivot.key) //pivot相當於在位置i上 j--; //從右向左掃描,查找第1個關鍵字小於pivot.key的記錄R[j] if(i<j) //表示找到的R[j]的關鍵字<pivot.key R[i++]=R[j]; //相當於交換R[i]和R[j],交換后i指針加1 while(i<j&&R[i].key<=pivot.key) //pivot相當於在位置j上 i++; //從左向右掃描,查找第1個關鍵字大於pivot.key的記錄R[i] if(i<j) //表示找到了R[i],使R[i].key>pivot.key R[j--]=R[i]; //相當於交換R[i]和R[j],交換后j指針減1 } //endwhile R[i]=pivot; //基准記錄已被最后定位 return i; } //partition
然后,對整個數組進行遞歸排序:
QUICKSORT(A, p, r) if p < r then q ← PARTITION(A, p, r) //關鍵 QUICKSORT(A, p, q - 1) QUICKSORT(A, q + 1, r)
算法導論中提到的快速排序的優化版本:就地重排
PARTITION(A, p, r) x ← A[r] //以最后一個元素,A[r]為主元 i ← p - 1 for j ← p to r - 1 //注,j從p指向的是r-1,不是r。 do if A[j] ≤ x then i ← i + 1 exchange A[i] <-> A[j] exchange A[i + 1] <-> A[r] return i + 1
本文重點:三向切分
快速排序什么時候不適用?
元素重復率特別高的時候。
如何優化?三向切分。前后各倆指針,總共四個指針。倆額外的指針指向跟待選元素相同的元素,最后全部置換到中間。
三向切分的好處?重復率高的時候,避免相同元素來回交換,節省交換次數。對於包含大量重復元素的數組,這個算法將排序時間從線性對數級降到了線性級別。

代碼:
#include <iostream> using namespace std; template <typename T> void sawp(T a[],int first,int second){ T temp; temp = a[first]; a[first] = a[second]; a[second] = temp; } template <typename T> int sort(T a[],int low,int high){ if(low < high){ int lt = low,i=low+1,gt = high; int temp = a[low]; while(i <= gt){ if(a[i] < temp){ sawp(a,lt++,i++); }else if(a[i] > temp){ sawp(a,i,gt--); }else{ i++; } } sort(a,low,lt-1); sort(a,gt+1,high); } } int main() { int a[] = {2,2,2,2,2,0,0,0,0,0,0,1,5}; //int a[] = {2,0,1,5}; int len = sizeof(a)/sizeof(int); sort(a,0,len-1); for (int i = 0; i < len; ++i) cout << a[i] << " "; cout << endl; }