快速排序(1)基本演算法實現,排序演算法實現
1. 基本演算法1.1 演算法原理
快速排序是一種分治排序演算法。它將數組劃分為左右兩個部分,然後分別對這兩部分排序。關鍵在劃分的過程中,它將重排數組,使的以下條件成立:
- 對於某個劃分元素指標 i ,a[i]將處於排序後數組的最終的位置上
- a[l],……,a[i-1] 中的元素都比a[i]小
- a[i+1],……,a[r] 中的元素都比a[i]大
我們通過劃分完成排序,然後遞迴的調用該方法處理子檔案,每一次劃分都會至少使一個元素放到它最終的位置上。
void quick_sort(Item a[], int l, int r){ if(r <= l) return; Item v = a[r]; int i = partation(a, l, r); quick_sort(a, l, i-1); quick_sort(a, i+1, r);}
1.2 劃分的實現過程
- 1.任選 a[r] 作為劃分元素,這個元素在劃分後處於它的最終位置上 v = a[r];
- 2.從數組左端開始掃描,直到找到一個比劃分元素大的元素;同時,從數組右側開始掃描,直到找到一個比劃分元素小的元素停止。
- 3.步驟2中使掃描停止的這2個元素在最終劃分數組中的位置是反的,因此交換這2個元
- 4.繼續步驟2和3,保證位於劃分元素指標左側的元素都比 v 小,位於右側的都比 v 大。
- 5.當掃描指標相遇時,交換劃分元素到它的最終位置,此次劃分完成
[注] 以上相等的元素也會被交換,後面會有改進演算法處理重複元素
int partation(Item a[], int l, int r) //劃分函數 { int i = l-1, j = r; Item v = a[r]; for(;;) { while(less(a[++i], v)); while(less(v, a[--j])) if(j == l) //v是數組中的最小值 break; if(j <= i) //i, j相遇 break; exch(&a[i], &a[j]); } exch(&a[i], &a[r]); //交換劃分元素到它最終位置 return i;}
劃分過程是不穩定的,因為每個元素都有可能被移到大量和它相等的元素(未經檢測到)的後面。至今,沒有基於數組的快速排序時穩定的。
2. 快速排序演算法的效能分析2.1.最壞情況
時間複雜度O(N22)次比較
如果調用一個大小為N的有序檔案,那麼所有的劃分都將退化,程式會調用自身N次,每次調用減少一個元素(左側N-1個,右側1個……);
N+(N−1)+(N−2)+……+2+1=(N+1)N2
2.2 最好情況
時間複雜度O(NlgN)次比較
如果每次劃分都能夠恰好把檔案分割成大小相等的兩部分,即滿足分治法
遞迴樹的深度是lgN,每層的比較O(N)
T(N)=2T(N/2)+N
上式中最後一項的f(N)=N是用於分解問題的代價(次數)
由主定理的情形2,f(N)=N=Nlog22log0N
所以T(N)=Nlog22∗log1N=NlgN
2.3 平均情況
時間複雜度O(NlgN)次比較
直觀來看就是,最好情況和最壞情況每層交替出現
在一個差的劃分後接一個好的劃分,以下配圖《演算法導論》P99
參考資料
1.《演算法:C語言實現》P192
2.《演算法導論》P98
3. 主定理:https://www.zybuluo.com/quinn/note/77106