高速排序為什麼快?

2021-09-07 10:42:32 字數 2792 閱讀 8980

這是以前思考過的問題,

它為什麼叫高速排序呢?思考無果,然後忘記了,然後昨天被問起。自然想不出非常好的答案。直到,看到了《暗時間》上有這個問題的答案。

在《暗時間》裡。作者劉未然並沒有直接給出答案。而是先說了兩個遊戲,猜數字和稱球。這兩個問題都非常好理解,而且不難解答。然而,令我豁然開朗的是,他們指向了同乙個思想,分而治之。把問題不斷分割一半又一半,直到答案水落石出。

回到正題,我們的目標是排序。不管哪個排序方法都是基於兩兩比較的。問題在於怎樣才幹降低比較的次數呢?舉個樣例,有這麼一組數:1,

2,3,4,5,15

。78,89,90,100

。200

;一共11

個。而且給出的初始順序是從小到大的。

如今要排成從大到小。高速排序的思想,就是從中抽取乙個數(稱為基準吧),然後大於基準的在一邊。小於或等於在還有一邊。

比方,如今隨機的抽取了78

。那麼1

。2,3,4,5,15

會在一邊。

89,90,100

,200

會在還有一邊。這時候,注意到,從這一刻開始,小於

78的那些數就再也沒有機會與大於

78的數進行兩兩比較了。高速排序用了分而治之的思想,儘管,因為隨機抽取。我們最好第一次抽到的是

15。這樣就平分了。可是沒關係。忽略掉這個隨機性因素,快排還是把大問題分成了兩個小問題,哪怕這兩個字問題不一定對等。僅僅要遞迴下去,結果水到渠成。

相反。我們看看相同是理論上與快排一樣的時間複雜度(

o(nlogn)

)的堆排序,就說最大堆吧,它把最大的元素移除後,把最後的葉子結點拿上來,是為了重建堆。可是,明顯。拿上的值是要比它的兩個葉子結點要小非常多的。它要比較非常多次,才幹回到合適的位置。

而且。我發現,在父結點的值與子樹結點的值比較前。左子樹和右子樹要先比較大小,然後拿出最大的那個才去跟父節點去比較大小。

兩次兩兩比較。才換來一次有意義的交換,如此迴圈下去,堆排序做了非常多無用功。

以上,從邏輯上分析了高速排序為什麼比歸併排序和堆排序快的原因。但。這還是不夠的。接著。從數學統計上分析他們的時間複雜度——

1)堆排序——

在構建堆的過程中,由於我們是全然二叉樹從最下層最右邊的非終端結點開始構建,將它與其孩子進行比較和若有必要的互換,對於每乙個非終端結點來說,事實上最多進行兩次比較和互換操作。因此整個構建堆的時間複雜度為o(n)。

在正式排序時,第i次取堆頂記錄重建堆須要用o(logi)的時間(全然二叉樹的某個結點到根結點的距離為.log2i.+1),而且須要取n-1次堆頂記錄,因此,重建堆的時間複雜度為o(nlogn)。

2)歸併排序——

假如用t(n

)表示使用歸併排序對

n個元素構成的陣列進行排序而使用的時間。用

mergetime

來表示將兩個子分組合併起來而花費的時間。

那麼t(

n)= t(n/2)+t(n/2) + mergetime

而mege

time

就是歸併兩個子陣列所耗費的時間。以最大時間來算。最多須要

n-1次來比較兩個子陣列的元素。然後

n次移動到暫時陣列中。

那麼mergetime

就是2n

-1 。

因此t(

n)= t(n/2)+ t(n/2) +2n

-1 。

3)高速排序——

在最差的情況下,要把

n個元素的陣列劃分,須要

n次比較和

n次移動。如果用

t(n)

來表示使用高速排序演算法來排序

n個元素的陣列所耗費的時間。那麼

t(n)= t(n/2)+ t(n/2) +2n

如此看來,有人可能就想到了。從數學公式上看,歸併排序還比快排要少個

1呢,是不是要快些?事實上,不是這種,請注意到那幾個字

"最差的情況下

",就是在我每次選擇的基準,取決於輸入的基準,都是最不理想的基準。恰好要移動最多次才幹達到目的。

可是這種情況的出現的概率是1/(2^n)

,非常非常小。並且。這是最普通的高速排序方法。先人提出了非常多改進優化的方案。當中一種被非經常常使用的就是採用隨機函式來選擇基準來避免最壞的情況的發生。

在暢銷的

acm資訊競賽教材《

演算法藝術與資訊學競賽

》上,作者也提出了關於快排的效率與優化問題——

正如我們所分析的。一旦我們採用隨機函式來產生基準,那麼時間複雜度計算公式裡。t(

n)= t(n/2)+ t(n/2) +2n裡2n

就不再是

2n了,或許是

1,或許是

2...

可是。最後的結果肯定是要比

2n小非常多了。

至於堆排序。明顯。

堆排序主要是堆調整的時間非常耗時,90%的時間耗在堆調整上

。因此在資料量大的時候。明顯是要落後非常多的。

至此,我想我明確了為什麼快排比其它兩種都要快了。由於它善於分解子問題。從不做無用功。

儘管有最糟糕的情況。可是這個是能夠最大限度減少其出現概率的。

有不允許見的,歡迎拍磚,謝謝。

epoll為什麼快

epoll是linux下的一種i o多路復用的操作方式,是event poll的意思 i o多路復用,舉個栗子,在酒吧,乙個服務員,10個顧客在喝酒,服務員有這麼幾種服務方式 服務員從第乙個顧客開始問,你要酒嗎,再問第二個,你要酒嗎,依次問下去,問完一圈,再從頭開始,服務員就是不停的在bbb,要酒嗎...

kafka 為什麼快

一般的 mq 每個訊息都有乙個狀態,這樣每個訊息狀態改變都要更新,增加了很多隨機讀寫。kafka 對每個 partition 只有乙個指標,而不是儲存每個訊息的狀態,所有在指標後面的訊息都是被消費過的訊息。這就去掉了很多 確認訊息 動作的隨機讀寫,通過一次移動指標,來確認多個訊息。很多訊息中介軟體,...

FastThreadLocal 為什麼快

threadlocal 大家都知道是執行緒本地變數,今天棧長再介紹乙個神器 fastthreadlocal,從字面上看就是 fast threadlocal,乙個快的 threadlocal?這到底是什麼鬼呢?一 fastthreadlocal 簡介 fastthreadlocal 並不是 jdk ...