標籤:style blog color io strong for ar art div
對於包含n個數的輸入數組來說,快速排序是一種最壞情況時間複雜度為theta(n^2)的排序演算法。雖然最壞情況時間複雜度很差,但是快速排序通常是實際排序應用中最好的選擇,因為它的平均效能非常好,期望時間複雜度是theta(nlgn),而且常數因子非常小,並可進行原址排序。
1. 快速排序的描述
快速排序可採用分治思想實現。
分解:數組A[p..r]被劃分為兩個(可能為空白)子數組A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一個元素都小於等於A[q],而A[q]也小於等於A[q+1..r]中的每個元素。
解決:通過遞迴調用快速排序,對數組A[p..q-1]和A[q+1..r]進行排序。
合并:因為子數組都是原址排序的,所以不需要合併作業,A[p..r]已經有序。
代碼實現如下:
1 void swap(int A[], int i, int j) { 2 int tmp = A[i]; 3 A[i] = A[j]; 4 A[j] = tmp; 5 } 6 7 int Partition(int A[], int p, int r) { 8 int x = A[r]; 9 int i = p - 1, j;10 11 for (j=p; j<r; ++j) {12 if (A[j] <= x) {13 ++i;14 swap(A, i, j);15 }16 }17 swap(A, i+1, r);18 return i+1;19 }20 21 void QuickSort(int A[], int p, int r) {22 int q;23 24 if (p < r) {25 q = Partition(A, p, r);26 QuickSort(A, p, q-1);27 QuickSort(A, q+1, r);28 }29 }
Partition過程總是選擇一個x=A[r]作為主元(Pivot Element),並圍繞該元素花費子數組A[p..r]。顯然,Partition的時間複雜度為theta(n),n = r-p+1。
2. 快速排序的效能
最壞情況下,劃分極不均勻,即劃分為n-1與0,則T(n) = T(0) + T(n-1) + theta(n),複雜度為theta(n^2);最好情況下,劃分足夠均勻,即花費為floor(n/2)與ceil(n/2)-1,則T(n) = 2T(n/2) + theta(n),複雜度為theta(nlgn)。通常,在劃分比例為常數比例的情況下,複雜度均為theta(nlgn)。
證明:最壞情況下快速排序複雜度為theta(n^2)。
T(n) = max(T(q)+T(n-q-1)) + theta(n),0<=q<=n-1,採用數學歸納法
<= max(c*q^2+c*(n-q-1)^2) + theta(n),0<=q<=n-1
= c*max(q^2+(n-q-1)^2) + theta(n)
<= c*n^2 - c*(2n-1) + theta(n).
只要c*(2n-1)顯著大於theta(n),結論即成立。
7.2.5 證明:以劃分比例1-a:a作遞迴樹,因為0<a<=1/2,所以1-a>=a,設高度為h,所以當葉結點深度最小(即高度最小)滿足(a^h)n = 1,解得h = -lgn/lga,同理,當葉結點深度最大(即高度最高)時,滿足((1-a)^h) = 1,解得
h = -lgn/lg(1-a)。注意,在第k層劃分後的數量一定為(a^x)*((1-a)(k-x))*,易知,劃分後的最大數量比例為(1-a)^k,最小數量比例a^k。分別令將這兩個比例*n為1,即可求解。
3. 快速排序的隨機化版本
即採用隨機抽樣的隨機化技術使得主要元素隨機選取,在等機率隨機選取的情況下,期望已耗用時間為O(nlgn)。
代碼如下:
1 void swap(int A[], int i, int j) { 2 int tmp = A[i]; 3 A[i] = A[j]; 4 A[j] = tmp; 5 } 6 7 int Partition(int A[], int p, int r) { 8 int x = A[r]; 9 int i = p - 1, j;10 11 for (j=p; j<r; ++j) {12 if (A[j] <= x) {13 ++i;14 swap(A, i, j);15 }16 }17 swap(A, i+1, r);18 return i+1;19 }20 21 int Randomized_Partition(int A[], int p, int r) {22 int n = r-p+1;23 int i = p+rand()%n, tmp;24 25 tmp = A[r];26 A[r] = A[i];27 A[i] = tmp;28 return Partition(A, p, r);29 }30 31 void QuickSort(int A[], int p, int r) {32 int q;33 34 if (p < r) {35 q = Randomized_Partition(A, p, r);36 QuickSort(A, p, q-1);37 QuickSort(A, q+1, r);38 }39 }
【演算法導論】學習筆記——第7章 快速排序