快速排序法的優化——雙路快速排序
上一節我們自己動手寫的乙個快速排序的演算法,在隨機數測試中表現得非常好,然而,我們在用高度有序的陣列進行測試的時候,發現快速排序的效率變得異常的低下,比歸併排序的效率低得多了,近似退回了o(n^2)的複雜度,這是為什麼呢?首先讓我們來分析一下歸併排序的演算法思想,歸併排序之所以能夠達到o(logn)的複雜度,多虧了遞迴,遞迴使得把陣列不斷的二分分小分到不能分為止,然後再從小的陣列開始解決,一直返回回去直到把最後乙個最大的陣列完成,任務就完成了,因此歸併的複雜度為o(nlogn);
而相對於快速排序來說,歸併排序的分類依據是從中間二分之一開始不停的分下去,這樣保證了分的每段陣列都是均勻的,也就是說形成的遞迴二叉樹相對來說比較的穩定,而對於快速排序的分類方法來說,快速排序是以陣列中的第一位元素為參考為來把陣列分類的,因此在特殊情況(陣列高度有序)的情況下,快速排序的分類可能導致陣列分的並不均勻,效率將會大大降低,達不到o(nlogn)的複雜度,分出來的陣列可能一邊多一邊少,如下圖所示:
當陣列完全有序的時候(極端情況),快速排序的劣勢就更加明顯的體現出來了:
因此,我們需要對快速排序進行優化,使其在碰到高度有序的陣列時也能夠輕鬆應對,
首先,我們分析快速排序之所以會退化的原因是陣列的分配方法導致陣列分類不均,因此我們需要修改快速排序的陣列分類方法,儘量減少這種情況的產生,因為我們每次都以陣列的第一位作為標準,這就產生了侷限,因此我們只要更改陣列的參考位置,不要每次都設定為陣列第一位就行了,我們可以用陣列中的任意乙個數來作為參考值,增加其隨機性來應對高度有序的陣列,我們可以用rand()方法生成乙個隨機數作為參考數字置的下標,在把arr【l】與其進行調換,避免陣列分配不均的情況,我們只需要修改_partion函式的定義即可:
int __partion(t arr,int l,int r)//分類子操作,最後返回v處於的位置下標
swap(arr[l],arr[j]);//把參考值提到中間來
return j;
}
雙路快速排序
雙路快速排序的時間複雜度為o nlog2n 空間複雜度為o n 雙路快速排序的核心思想 單路快排會將等於v的元素分配在左側或者右側,當陣列中有大量重複元素時,這將會導致左右兩側的元素數量極度不均衡,時間複雜度退化到o n 2 如下圖所示 雙路快排是將等於v的部分近乎平均的分配在左右兩側,避免了該問題...
快速排序之雙路快速排序
我們知道快排的一般步驟是 1.選取最左邊的數為基準數 2.從右邊開始選取乙個小於基準數的元素 3.從左邊開始選取乙個大於基準數的元素 4.交換這兩個元素 5.重複2 3 4步直至左右兩邊移到同一位置,交換基準數與當前元素 void quick sort int begin,int end left ...
C 實現快速排序 雙路快速排序 三路快速排序
從左向右依次遞迴 如果 陣列中的元素都相等,就會變成 n 級別的複雜度演算法 public class quicksort public static void sort t arr where t system.icomparable public static void sort2 t arr ...