堆排序是一種選擇排序。
選擇排序:每趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排序的記錄序列末尾,直到全部排序結束為止。
1. 演算法思想
堆排序是利用堆的性質進行的一種選擇排序。
動態效果示意圖:
堆是一棵順序儲存的完全二叉樹。
其中每個結點的關鍵字都不大於其孩子結點的關鍵字,這樣的堆稱為小根堆。
其中每個結點的關鍵字都不小於其孩子結點的關鍵字,這樣的堆稱為大根堆。
舉例來說,對於n個元素的序列當且僅當滿足下列關係之一時,稱之為堆:
ri <= r2i+1 且 ri <= r2i+2 (小根堆)
ri >= r2i+1 且 ri >= r2i+2 (大根堆)
其中i=1,2,…,n/2向下取整;
如上圖所示,序列r是乙個典型的小根堆。
堆中有兩個結點,元素3和元素8。
元素3在陣列中以r[0]表示,它的左孩子結點是r[1],右孩子結點是r[2]。
元素8在陣列中以r[1]表示,它的左孩子結點是r[3],右孩子結點是r[4],它的父結點是r[0]。可以看出,它們滿足以下規律:
設當前元素在陣列中以r[i]表示,那麼,
(1) 它的左孩子結點是:r[2*i+1];
(2) 它的右孩子結點是:r[2*i+2];
(3) 它的父結點是:r[(i-1)/2];
(4) r[i] <= r[2*i+1] 且 r[i] <= r[2i+2]。
首先,按堆的定義將陣列r[0..n]調整為堆(這個過程稱為建立初始堆),交換r[0]和r[n];
然後,將r[0..n-1]調整為堆,交換r[0]和r[n-1];
如此反覆,直到交換了r[0]和r[1]為止。
以上思想可歸納為兩個操作:
(1)根據初始陣列去構造初始堆(構建乙個完全二叉樹,保證所有的父結點都比它的孩子結點數值大)。
(2)每次交換第乙個和最後乙個元素,輸出最後乙個元素(最大值),然後把剩下元素重新調整為大根堆。
當輸出完最後乙個元素後,這個陣列已經是按照從小到大的順序排列了。
先通過詳細的例項圖來看一下,如何構建初始堆。
設有乙個無序序列 。
構造了初始堆後,我們來看一下完整的堆排序處理:
還是針對前面提到的無序序列 來加以說明。
比如如下陣列 堆排序前如下:
進行堆排序後如下:
最大堆的儲存結構如下:
接著,最後一步,堆排序,進行(n-1)次迴圈。
相信,通過以上兩幅圖,應該能很直觀的演示堆排序的操作處理。
看完上面所述的流程你至少有乙個疑問:
如何確定最後乙個非葉子結點?
其實這是有乙個公式的,設二叉樹結點總數為 n,則最後乙個非葉子結點是第⌊n/2⌋個。
2. **+結果:
3. 演算法分析
3.1 堆排序演算法的總體情況
3.2 時間複雜度
首先計算建堆的時間,也就是下面的**,
// 迴圈建立初始堆
for (int i = length / 2; i >= 0; i--){
heapadjust(list, i, length);
n 個結點,從第 0 層至第logn層。對於第 i 層的2i個點如果需要往下走logn−i步,那麼把走的所有步相加得:
接下來就是排序的時間,即下面的**:
// 進行n-1次迴圈,完成排序
for (int i = length - 1; i > 0; i--){
// 最後乙個元素和第一元素進行交換
int temp = list[i];
list[i] = list[0];
list[0] = temp;
// 篩選 r[0] 結點,得到i-1個結點的堆
heapadjust(list, 0, i);
heapadjust() 耗時logn,共 n 次,故排序時間為o(nlogn)。
堆的儲存表示是順序的。因為堆所對應的二叉樹為完全二叉樹,而完全二叉樹通常採用順序儲存方式。
當想得到乙個序列中第k個最小的元素之前的部分排序序列,最好採用堆排序。
3.3 演算法穩定性
堆排序是一種不穩定的排序方法。
因為在堆的調整過程中,關鍵字進行比較和交換所走的是該結點到葉子結點的一條路徑,因此對於相同的關鍵字就可能出現排在後面的關鍵字被交換到前面來的情況。
推薦閱讀:
★ 求職經驗:點這裡
★ 演算法刷題:點這裡
★ 投資理財:點這裡
★ ai很簡單:
★ 掃盲科普:點這裡
堆排序穩定性舉例 穩定排序和不穩定排序
這幾天筆試了好幾次了,連續碰到乙個關於常見排序演算法穩定性判別的問題,往往還是多選,對於我以及和我一樣拿不準的同學可不是乙個能輕易下結論的題目,當然如果你筆試之前已經記住了資料結構書上哪些是穩定的,哪些不是穩定的,做起來應該可以輕鬆搞定。本文是針對老是記不住這個或者想真正明白到底為什麼是穩定或者不穩...
堆排序穩定性舉例 常見排序演算法的穩定性分析
一 不穩定排序演算法有哪些 1 堆排序 2 希爾排序 3 快速排序 4 選擇排序 口訣 一堆 堆 希爾 希爾 快 快速 選 選擇 二 常見排序演算法穩定性分析 1 堆排序穩定性分析 我們知道堆的結構是節點i的孩子為 2 i 和 2 i 1 節點,大頂堆要求父節點大於等於其 2 個子節點,小頂堆要求父...
排序6 堆排序
6.1概念以及分類 6.1.1樹 學堆需要的基礎 度的概念 出度 樹中乙個數字下面的數如 上圖2的出度為4,4的出度為0 入度 上乙個數 二叉樹 整個樹中最多有兩個分叉 出度 子節點,父節點 2,3是1的孩子節點分別為左孩子,右孩子。1是2,3的父節點 或雙親節點 2是4,5的父節點。葉子結點 4,...