1、快速排序
通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
2、排序的過程
3、代碼實現
三數取中法代碼:
//優化一:三數取中法,避免出現最壞的情況 int GetMidIndex(int* a,int left,int right) { assert(a); int mid = left + (right- left)/2; if(a[left] > a[right]) { if(a[mid] > a[left]) { return left; } else { if(a[mid] > a[right]) return mid; else return right; } } else//right大 { if(a[mid] > a[right]) return right; else//right 大 { if(a[mid] > a[left]) return mid; else return left; } } }
快速排序的代碼:
int PartSort1(int* a,int left,int right) { int mid = GetMidIndex(a,left,right); int key = a[mid]; int begin = left; int end = right-1; swap(a[mid],a[right]); while(begin <end) { while(begin <end && a[end] >=key) end--; while(begin <end && a[begin] <key) begin++; if(begin < end) swap(a[begin],a[end]); } if(a[begin] > a[right]) { swap(a[begin],a[right]); return begin; } else return begin; } void QuickSort(int* a,int left,int right) { //快速排序的第二種優化,將插入排序與快速排序結合 assert(a); if(left >= right) return; if(right -left < 16) { InsertSort(a+left,right-left+1); return; } else { int ret = PartSort1(a,left,right); QuickSort(a,left,ret-1); QuickSort(a,ret+1,right); } }
另外兩種快速排序的方法:
//挖坑法 int PartSort2(int* a,int left,int right) { int mid = GetMidIndex(a,left,right); int key = a[mid]; int begin = left; int end = right;//初始時的坑 swap(a[mid],a[right]); while(begin < end) { while(begin < end && a[begin] <= key) begin++; if(begin < end) { a[end] = a[begin];//begin的位置變爲坑 } while(begin < end && a[end] >= key) end--; if(begin < end) { a[begin] = a[end]; } } //跳出循環後,begin的位置爲坑,將key放入 a[begin] = key; return begin; } //雙指針法 int PartSort3(int* a,int left,int right) { int mid = GetMidIndex(a,left,right); int key = a[mid]; swap(a[mid],a[right]); int cur = 0; int prev = -1; while(cur < right) { if(a[cur] < key && (++prev != cur)) swap(a[cur],a[prev]); cur++; } prev++; swap(a[prev],a[cur]); return prev; }
4、時間複雜度
1)最好:O(N*logN)
在最好情況下,每次劃分所取的基準都是當前無序區的"中值"記錄,劃分的結果是基準的左、右兩個無序子區間的長度大致相等。總的關鍵字比較次數:O(NlogN)。
2)最壞:O(N*N)(key取得的值接近最大或最小)
最壞情況是每次劃分選取的基準都是當前無序區中關鍵字最小(或最大)的記錄,劃分的結果是基準左邊的子區間爲空(或右邊的子區間爲空),而劃分所得的另一個非空的子區間中記錄數目,僅僅比劃分前的無序區中記錄個數減少一個。時間複雜度爲O(N*N)。