序列範圍[l,u]
選取第乙個元素為樞紐值,然後圍繞t劃分陣列:
m=a-1
for i =[a,b]
if x[i]
迴圈終止後有:
此時交換x[l]和x[m]即可。
**:void qsort1(int *x, int l, int u)
swap(x[l], x[m]);
qsort(x, l, m - 1);
qsort(x, m + 1, u);
}
可以通過qsort1(0,n-1)來排序陣列x[n]
qsort1函式能夠快速完成隨機序列的排序,但是對於序列由n個相同的元素組成時,效能就非常差,從**中我們可以看出,當序列元素相同時,qsort1的時間複雜度為o(n²)。
使用雙向劃分可以解決這個問題。
對於上面的快速排序,我們可以稍微改進:
**:
void qsort2(int *x, int l, int u)
qsort2(x, l, m - 1);
qsort2(x, m + 1, u);
}
通過將從左到右的迴圈修改為從右向左,從而省去一次swap:
最後一次迴圈結束前:
使用雙向劃分的快速排序:
i指示小於等於t的增長邊界,j指向大於等於t的增長邊界。
**:
void qsort3(int *x, int l, int u)
swap(x[l], x[j]);
qsort3(x, l, j - 1);
qsort3(x, j + 1, u);
}
當while(1)迴圈結束時,序列變成:
所以最後進行swap(x[l],x[j])。
這裡特別要注意i和j,swap的是x[j]不是x[i]!!!
我們注意到:
while (++i <= u && x[i] < t);
while (x[j] > t);
為什麼第二個while不寫成while (--j >= l && x[j] > t)?因為沒有必要,序列的第乙個元素為t,當j==l時有x[j]==t,該迴圈總是能終止不會發生越界情況(相當於第乙個元素為哨兵),而第乙個while則不同。
當遇到和t相同的元素時,停止掃瞄並交換x[i]和x[j],這樣做雖然交換的次數增加了,但卻將所有元素相同的最壞情況變成了差不多需要nlogn次比較的最好情況。
但是,如果序列已經排好序了,上面的**效能依然會下降到o(n²),原因是我們每次都是選擇第乙個元素作為劃分元素。我們可以通過隨機選擇劃分元素來解決:
int c=randint(l,u);
swap(x[l],x[c]);
其中函式randint(l,u)產生[l,u]之間的隨機數。 幾種快速的排序演算法
鴿巢排序,排序位元組串 寬位元組串最快的排序演算法,計數排序的變種 將計數緩衝區大小固定,少一次遍歷開銷 速度是stl中std sort的20多倍 更重要的是實現極其簡單!缺點是需要乙個size至少等於待排序陣列取值範圍的緩衝區,不適合int等大範圍資料。多一次遍歷的計數排序,排序位元組串的話速度約...
快速排序演算法的幾種版本及實現
寫在前面的話 最近系統地學習了快速排序演算法,在此作一筆記。主要包括快排的各種版本 普通版本,改進的普通版本,隨機化版本,三數值取中分割版本和stooge版本。對各版本進行了簡要分析,並給出了具體實現。演算法導論 對快排的描述 快速排序是基於分治模式的,下面是對乙個典型子陣列a p.r 排序的分治過...
幾種排序演算法 (快速排序 堆排序)
快速排序 include usingnamespacestd voidqsort inta,intlow,inthigh intfirst low intlast high intkey a first 用字表的第乙個記錄作為樞軸 while first last a first a last 將比...