快排**的第一句便是選取基準點,此後資料的移動根據這個基準點的大小進行調整,如果基準點選取的不好,將會導致快排的效率低下,經過測試,普通的快排演算法針對(1)近乎有序的數列;(2)含有大量重複資料的數列;這兩種情況時效率將會變得非常低,針對這些情況,經過適當的優化可以使快排達到很高的效率。
快排將選取的基準點經過調整放到合適的位置,之後將這個基準點左右兩邊的區間分別遞迴的進行快排,如果基準點的資料比較小,將會導致調整後基準點處於靠近兩側的位置,那麼兩邊的區間長度將會嚴重失去平衡
對於乙個近乎有序的數列,當直接使用第乙個元素作為基準點的時候,將會導致下圖的情況
如果數列非常接近有序
可以看到此時快排的遞迴過程生成的遞迴樹的平衡性非常差,不能保證高度是logn,進而導致了效率變低,針對這種情況,只需改變選取基準點的方式就可以提高演算法的效率。
三數取中法:指的是選取基準點之前我們可以拿出數列中間位置元素的值,將它和首尾的元素進行比較,之後將這三個數中的中間大的數交換到數列首位的位置,之後將這個數作為基準點,盡量減小之後的分割槽後左右兩邊的區間長度之差。
隨機交換法:指的是選取基準點之前設計隨機種子,通過隨機函式得到乙個在數列長度內的數,將這個隨機數作為索引所指的數和第乙個元素進行交換,之後將首位元素作為基準點。即隨機選乙個數放到首位的地方。這樣一來,第一次就將最小的數交換到首位的概率是非常小的,第二次將次小的數交換到首位的概率依然非常的小。
比如隨機生成乙個含有15萬個資料的陣列,範圍是從0~10,那麼陣列中將含有非常多的重複資料,對這個陣列使用上述的快排排序時,時間幾乎又是回到了o(n^2)的級別,原因如下
在之前的分割槽演算法中,由於含有大量的重複資料,將會導致分出來的左右區間如圖所示,兩個區間的長度比例完全失衡,導致了演算法的時間複雜度上公升,針對這種情況,需要對分割槽操作做適當的修改,思路是將小於基準點的數全部放到左邊,大於基準點的數全部放到右邊,
具體操作:從右向左掃瞄時,如果元素值大於基準點,則繼續,否則停止,如圖j所指的位置,從左向右掃面時,當元素值小於基準點,則繼續,否則停止,如圖i所指的位置
經過上述掃瞄後,i和j停在了相應的位置,此時要做的是,交換i和j分別所指的元素即可,這樣一來,左邊的全部都是小於等於基準點的,右邊的全部都是大於等於基準點的,這樣做的好處是,對於等於基準點的元素,將他們分別放到了左右的兩個區間,而不是像之前那樣完全放在同一邊,導致區間長度不平衡。因此,通過將等於基準點的元素分配到不同區間,保證了左右區間長度盡可能平衡,提公升了演算法的效率
經過測試,對於含有大量重複資料的陣列,演算法的效率基本回到了o(nlogn)的級別。
3路法同樣是針對含有大量重複數列的優化,不同於之前的快排方法,3路法的思想是將數列分成3個區間,分別是小於、等於和大於基準點的區間,那麼分割槽之後,對於等於基準點的區間內的元素,我們就不需要對其做任何處理了,只需要遞迴的處理小於和大於基準點的元素即可。
如圖,需要多設定幾個索引,橙色部分全部是小於v的資料,紫色為大於v的資料,i所指的為待處理的資料。
(1)當待處理的資料小於v時,只需將i所指的元素和等於v的區間的第乙個元素交換即可,即將e換到lt之後的位置,lt++,i++
(2)i所指元素大於v時,將其換到大於基準點的區間的第乙個位置即可,即交換i和gt-1的元素,gt--,i不變
(3)i所指元素等於v時,直接i++
**
templatevoid qsort3ways(t k, int l, int r)
swap(k[l], k[rand() % (r - l + 1) + l]);
t temp = k[l];
int lt = l; // k[l+1...lt] < v
int gt = r + 1; // k[gt...r] > v
int i = l + 1; // k[lt+1...i) = v
while (i < gt) else if (k[i] > temp) else
}swap(k[l], k[lt]);
qsort3ways(k, l, lt - 1);
qsort3ways(k, gt, r);
}templatevoid quicksort3ways(t k, int len)
優化的快速排序
快速排序 void swap int a,int b int median3 int a,int left,int right if a left a right if a center a right 將中值放在倒數第二個位置並作為樞紐元返回 swap a center a right 1 ret...
快速排序的優化
快速排序的優化 1,隨機選取基準法 2,三分基準法 3,當代排序陣列當中資料比較少的時候用直接插入法 4,聚集相同元素法 基準一樣的元素 一,當序列有序的時候快速排序的時間複雜度將會變成o n2 例如 1 2 3 4 5 6 7 8 9 所以我們要採取優化來使基準不會一直被選取最小的那個數。這時候我...
快速排序的優化
快排是效率很高的排序方法,但仍有一些問題,如穩定性不高,處理小陣列效率不算很高,處理重複數字效率低,難以選取最優中軸 主要有三種優化方式 前 中 後三者排序 並把中軸放在high 1的位置 如 會處理為 public static void dealpivot int arr,int left,in...