二種快排穩定實現

2021-08-14 12:15:29 字數 2881 閱讀 6178

三路快排

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 重新排序數列...