三路快排
void
quicksort
(int
a, intleft,
intright)
i++; }
/* *
工作指標
j從左向右不斷掃瞄,找大於或者等於錨點元素的元素 */
while
(left <= j && a[j] >=pivot)
j--; }
/* *
如果兩個工作指標
i j相遇則一趟遍歷結束 */
if(i >= j)
break;
/* *
將左邊大於
pivot
的元素與右邊小於
pivot
元素進行交換 */
swap(a, i,j);
i++;
j--; }
/* *
因為工作指標
i指向的是當前需要處理元素的下乙個元素 *
故而需要退回到當前元素的實際位置,然後將等於
pivot
元素交換到序列中間 */
i--;
p--;
while
(p >= left) /*
* 因為工作指標
j指向的是當前需要處理元素的上乙個元素 *
故而需要退回到當前元素的實際位置,然後將等於
pivot
元素交換到序列中間 */
j++;
q++;
while
(q <= right)
/* * 遞迴遍歷左右子串行 */
quicksort(a,left, i);
quicksort(a, j,right); }
private
void
quick
(int
a) }
private
void
swap
(int
arr,
inta,
intb)
雙關鍵字快排
其實如果理解了快排的原理,雙關鍵字快排其實是很簡單的。
因為快排的思想是在待排序序列中選取乙個記錄,讓它左邊的都小於等於它,右邊的都大於等於它,如此遞迴。
那麼雙關鍵字的思想就順其自然:在待排序序列中選取乙個記錄,讓它左邊的第一關鍵字小於它,或者第一關鍵字等於它但是第二關鍵字小於它;右邊的第一關鍵字大於它,或者第一關鍵字等於它但是第二關鍵字大於它,如此遞迴。(讀起來有點繞,但是對照上一句仔細讀讀還是可以讀懂的)
下面附上**:
1#include
2#include34
void
myqsort(
int*a,
int*b,
intleft,
intright)526
}27if(i
28if
(left29}
3031
intmain()
3243
myqsort(a,b,
0,n-1);
44for
(i=0
;i45
48free
(a);
49free
(b);
50return0;
51}其實這個程式就把不穩定的快排變成了穩定的快排了!(因為新增了乙個關鍵字,對於相等的就實現了本來在前面的還在前面)
時間複雜度推導
在最優情況下,partition每次都劃分得很均勻,如果排序n個關鍵字,其遞迴樹的深度就為.log2n.+1(.x.表示不大於x的最大整數),即僅需遞迴log2n次,需要時間為t(n)的話,第一次partiation應該是需要對整個陣列掃瞄一遍,做n次比較。然後,獲得的樞軸將陣列一分為二,那麼各自還需要t(n/2)的時間(注意是最好情況,所以平分兩半)。於是不斷地劃分下去,我們就有了下面的不等式推斷。
1. t(n)≤2t(n/2) +n,t(1)=0
2. t(n)≤2(2t(n/4)+n/2) +n=4t(n/4)+2n
3. t(n)≤4(2t(n/8)+n/4) +2n=8t(n/8)+3n
4. ……
5. t(n)≤nt(1)+(log2n)×n= o(nlogn)
也就是說,在最優的情況下,快速排序演算法的時間複雜度為o(nlogn)。
在最壞的情況下,待排序的序列為正序或者逆序,每次劃分只得到乙個比上一次劃分少乙個記錄的子串行,注意另乙個為空。如果遞迴樹畫出來,它就是一棵斜樹。此時需要執行n‐1次遞迴呼叫,且第i次劃分需要經過n‐i次關鍵字的比較才能找到第i個記錄,也就是樞軸的位置,因此比較次數為
,最終其時間複雜度為o(n2)。
快速排序平均需要大約2nlnn次比較,來對長度為n的排序關鍵字唯一的序列進行排序。 證明也比較簡單:假設cn
為快速排序平均花在比較上的時間,初始c0=c
1=0,對於n>1的情況,有:其中n+1是分割時的比較次數,
表示將序列分割為0,和n-1左右兩部分的概率為1/n, 劃分為1,n-2左右兩部分的概率也為1/n,都是等概率的。然後對上式左右兩邊同時乘以n,整理得到:
然後,對於n為n-1的情況:
然後左右兩邊同時除以n(n+1),得到:
可以看到,這是乙個遞迴式,我們將 遞迴展開得到:
然後處理一下得到:
就空間複雜度來說,主要是遞迴造成的棧空間的使用,最好情況,遞迴樹的深度為log2n,其空間複雜度也就為o(logn),最壞情況,需要進行n‐1遞迴呼叫,其空間複雜度為o(n),平均情況,空間複雜度也為o(logn)。
可惜的是,由於關鍵字的比較和交換是跳躍進行的,因此,快速排序是一種不穩定的排序方法。
C語言實現穩定的快排
關於這種穩定的快排的思路,請看我之前的這篇文章 對數器 python實現穩定快排 下面是實現 include include include intsplit char str,int datalist 20 const char separator return n void quicklysor...
python實現快排演算法 python快排演算法詳解
快排是python經典演算法之一。1 下面講解的是什麼是快排和快排的圖示。2 快排是一種解決排序問題的運算方法。3 快排的原理 在陣列中任意選擇乙個數字作為基準,用陣列的資料和基準資料進行比較,比基準數字打的數字的基準數字的右邊,比基準數字小的數字在基準數字的左邊,第一次排序之後分為比基準資料大或比...
快排簡單實現
沒事再寫下經典的快排 感覺順手多了 還是比較懶,wiki 介紹如下 快速排序是一種 分而治之 各個擊破 的觀念。快速排序使用分治法 divide and conquer 策略來把乙個序列 list 分為兩個子串行 sub lists 步驟為 從數列中挑出乙個元素,稱為 基準 pivot 重新排序數列...