一、演算法描述
快速排序是基於分治法的排序演算法的一種。
三個步驟:
分解:數組A[p..r]被劃分成兩個子數組A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每個元素都小於A[q],而且,小於等於A[q+1..r].下標q也在這個劃分過程中進行計算。
解決:通過遞迴調用快速排序,對子數組A[p..q-1]和A[q+1..r]排序。
合并:遞迴到最後已經全部有序,不許要合并處理。
一趟快速排序的演算法是:
1)設定兩個變數I、J,排序開始的時候:I=0,J=N-1;
2)以第一個數組元素作為關鍵資料,賦值給key,即 key=A[0];
3)從J開始向前搜尋,即由後開始向前搜尋(J=J-1即J--),找到第一個小於key的值A[j],A[j]與A[i]交換;
4)從I開始向後搜尋,即由前開始向後搜尋(I=I+1即I++),找到第一個大於key的A[i],A[i]與A[j]交換;
5)重複第3、4、5步,直到 I=J; (3,4步是在程式中沒找到時候j=j-1,i=i+1,直至找到為止。找到並交換的時候i, j指標位置不變。另外當i=j這過程一定正好是i+或j-完成的最後令迴圈結束。)
二、代碼清單
/*QuickSort*/void quickSort(elementType a[],int size){ q_Sort(a,0,size-1);}void q_Sort(elementType a[],int left,int right){ if(right<=left) return; int i=left,j=right; //將數組最後一個元素賦給key elementType key=a[right]; while(i<j) { //從前往後找 while(a[i]<key&&i<j) i++; if(i<j) { a[j]=a[i]; j--; } //從後往前找 while(a[j]>key&&i<j) j--; if(i<j) { a[i]=a[j]; i++; } } a[i]=key; q_Sort(a,left,i-1); q_Sort(a,i+1,right);}
三、時間複雜度討論
整體複雜度是O(nlgn).
最壞情況是原序列有序,每次劃分成兩部分都是1,n-1,快排退化,時間複雜度O(n^2)。
為了避免退化,解決方案是隨機取key值,或是每次取開頭,中間,結尾三個數、取這三個當中中間的數為key等技巧進行最佳化。
參考書籍:演算法導論(第二版)
《ACM-ICPC演算法基礎》