當前位置: 華文星空 > 知識

為什麽在平均情況下快速排序比堆排序要優秀?

2014-05-22知識

對於這個問題,我們主要可以從工作機理、原理分析以及復雜度比較三個角度去理解。

1 工作機理

設有任意一陣列, C = [x1, x2, x3, …, Xn],

目標: 將其從大到小進行排序;就快排和堆排兩個演算法的過程作出如下分析:

  • 快速排序過程:
  • S1. 在陣列中定義兩個指標 , p1, p2; 指標p1是從左向右,p2是從右向左。

    S2. 取陣列的第一個元素作為基準(理論上可以取任意一個),利用上述兩個指標找出比基準小的放在左邊,比基準大的放在右邊。

    S3. 在第二步中調整完後,基準值會將原陣列分成三部份,[比基準小的數],[基準], [比基準大的數]

    S4. 把S3中的 [比基準小的數], [比基準大的數] 代入S2 ;

  • 堆排序過程:
  • S1. 初始化大頂堆;(該結構上是一顆完全二叉樹,該過程又叫構造堆過程。)

    S2. 將最後一個元素與第一個元素互換;

    S3. 重新調整至大頂堆,代入S1;

    2 原理分析

    (1) 快速排序原理

    其實就是透過不斷產生新的基準值,將原陣列不斷地劃分成兩部份,然後進行大小調整。這樣做的原因是因為它在叠代過程中會產生一個不可控的序列,就是[比基準小的數], [比基準大的數]。我們只知道這兩個子陣列裏面的元素比基準大或小,實質上該陣列內部元素之間的大小關系我們不清楚, 但是該演算法告訴我們可以透過不斷選取新的基準將陣列劃分,可以使得這些「不可控的序列」逐漸變小直至消失,此時陣列已經排好序,這就是快速排序要做的事情。

    (2) 堆排序原理

    其實就是利用了大頂堆的性質,而實質上它又同時是一顆完全二叉樹。大頂堆的層級大小性質可以幫助我們控制部份數據的大小關系,完全二叉樹的順序儲存性質可以幫助我們把數據按一定大小關系排列起來。大頂堆告訴我們上一層的數據比下一層的數據大,但我們並不清楚每一層內部元素之間的大小關系, 我們只能透過不斷調整堆,讓它自身不斷生成大頂堆,這樣會使每一層內部元素的大小產生調整,調整範圍也會越來越小,直至排序完畢,這就是堆排序要做的事情。

    3 時間復雜度比較分析

    上面大多都是陳鋪序述,熟悉演算法的朋友可以跳過。下面我們聚焦於兩個排序演算法之間的叠代過程中的一些小細節分析:

    (1) 在快排的叠代過程中,我們所處理的 [比基準大的數],[比基準小的數] 序列中,在進行兩個數之間大小比較時,在該局部範圍內,產生「大於」或者「小於」的可能性是一樣的。這意味著每比較一次必然會產生一次有意義的比較結果,會縮減接下來叠代的掃描工作量。

    (2) 我們再來看看堆排序。在每一次進行重新堆調整的時候,我們在叠代時其實就已經知道,上一層的結點值一定是比下面大的。為了打亂堆結構把最後一個元素與頂堆互換時,此時我們也已經知道,互換後的元素是一定比下一層的數要小的。而在叠代時為了調整堆我們還是要進行一次已經知道結果的比較,這無疑是沒有什麽價值的,也就是產生了一次沒有意義的比較,對接下來的叠代工作量並沒有任何進展。

    由上述不難看出,兩種排序方式都是采用了分治的思想,註意到該兩種演算法在叠代實作時,大體上都分成了兩條掃描路線:

    A. 快速排序:

    一是基於基準值調整大小時,對整個陣列各項元素的掃描,該部份時間復雜度分N.

    二是不斷產生新的基準值對陣列進行劃分所產生的叠代次數,該部份時間復雜度為log(n).

    (log(n)的由來:原陣列不斷二分會產生的序列為n, n/2, n/4, …, n/2^k, 其中k的值就是需要叠代的次數,而n/2^k最終會收斂於1,亦即n/2^k=1時, n=2^k, log轉換: log(n) = k)

    B. 堆排序:

    一是在產生頂堆時對各個結點數之間的比較,會涉及到整個陣列元素的掃描,該部份時間復雜度為n.

    二是在調整堆的時候,對非葉子節點的掃描,該部份時間復雜度為log(n);

    兩者平均時間復雜度均為o(nlog(n))。

    對於快速排序 ,當陣列的各項元素均相等,又或者是每一次叠代時選到的基準值恰恰是陣列裏的最值,此時的快排時間復雜度就為o(n^2). 因為此時每一次叠代劃分陣列所發生的比較都是無效比較。而這樣的情況發生的概率為 1 / (n * (n/2) * (n/4) ...(n/2^k)), 這是非常小的概率事件了。

    而對於堆排序 ,礙於堆的特性,在叠代時所產生的無效比較概率是相對較大甚至為100%。 因此,在實際使用中,快速排序的使用常優於堆排序。

    本次作答如有錯漏或不同見解,歡迎指出。