知乎上有一個問題是這樣的:算法
堆排序是漸進最優的比較排序算法,達到了O(nlgn)這一下界,而快排有必定的可能性會產生最壞劃分,時間複雜度可能爲O(n^2),那爲何快排在實際使用中一般優於堆排序?測試
昨天恰好寫了一篇關於快排優化的文章,今天再多作一個比較吧。首先先看一個排序算法圖:優化
排序方法 | 平均狀況 | 最好狀況 | 最壞狀況 | 輔助空間 | 穩定性 |
---|---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 穩定 |
簡單選擇排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 穩定 |
直接插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 穩定 |
希爾排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不穩定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不穩定 |
歸併排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 穩定 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn)~O(n) | 不穩定 |
能夠看到,到達nlogn級別的排序算法,一共有三種,分別是堆排序,歸併排序以及快速排序,其中只有歸併排序最穩定。那麼,爲何要說快速排序的平均狀況是最快的呢?code
實際上在算法分析中,大O的做用是給出一個規模的下界,而不是增加數量的下界。所以,算法複雜度同樣只是說明隨着數據量的增長,算法時間代價增加的趨勢相同,並非執行的時間就同樣,這裏面有不少常量參數的差異,好比在公式裏各個排序算法的前面都省略了一個c,這個c對於堆排序來講是100,可能對於快速排序來講就是10,但由於是常數級因此不影響大O。排序
另外,即便是一樣的算法,不一樣的人寫的代碼,不一樣的應用場景下執行時間也可能差異很大。下面是一個測試數據:table
測試的平均排序時間:數據是隨機整數,時間單位是s 數據規模 快速排序 歸併排序 希爾排序 堆排序 1000萬 0.75 1.22 1.77 3.57 5000萬 3.78 6.29 9.48 26.54 1億 7.65 13.06 18.79 61.31
堆排序每次取一個最大值和堆底部的數據交換,從新篩選堆,把堆頂的X調整到位,有很大多是依舊調整到堆的底部(堆的底部X顯然是比較小的數,纔會在底部),而後再次和堆頂最大值交換,再調整下來,能夠說堆排序作了許多無用功。class
總結起來就是,快排的最壞時間雖然複雜度高,可是在統計意義上,這種數據出現的機率極小,而堆排序過程裏的交換跟快排過程裏的交換雖然都是常量時間,可是常量時間差不少。方法