1、概述
堆排序是指利用堆這種資料結構所設計的一種排序演算法。
堆是乙個近似完全二叉樹,並同時滿足堆積的性質:子節點的鍵值或索引總是大於/小於它的父結點。
堆又分為 大頂堆 和小頂堆,大頂堆的特點是 該完全二叉樹的根節點比其左右節點都要大,小頂堆的特點是 在小頂堆中根節點比左右子節點的值都要小。
1)大頂堆
假設根節點的編號是 i ,那麼該根節點的左孩子的編號是 2i,右孩子的編號是 2i+1。
根節點和子節點的關係為:k(i)>=k(2i)、k(i)>=k(2i+1) i>=1
2)小頂堆
假設根節點的編號是 i ,那麼該根節點的左孩子的編號是 2i,右孩子的編號是 2i+1。
根節點和子節點的關係為:k(i)<=k(2i)、k(i)<=k(2i+1) i>=1
2、演算法原理
思想:將無序的序列構建成大頂堆/小頂堆,最後將排好序的堆轉換成大頂堆/小頂堆的層次遍歷的序列,即為所求
步驟:1)最大堆調整max_heapify:將堆的末端子節點作調整,使得子結點永遠小於父結點,其目的是保持最大堆的性質,是建立最大堆的核心子程式
2)建立最大堆build_max_heap:將堆所有資料重新排序。其目的是將乙個陣列改造成最大堆,接受陣列和堆大小兩個引數,build-max-heap 將自下而上的呼叫 max-heapify 來改造陣列,建立最大堆
3)堆排序heapsort:移除位在第乙個資料的根節點,並做最大堆調整的遞迴運算
3、舉例
以 [62, 88, 58, 47, 62, 35, 73, 51, 99, 37, 93]為例
1)先將上述序列從左往右存入完全二叉樹中
2)構建 大頂堆
(1)先對子樹進行調整,將其調整為大頂堆。找到完全二叉樹最下方最小的以62為根節點的子樹,先比較62的兩個節點,93最大,由於62<93,所以交換62與93的位置。該子樹的大頂堆構建完成
(2)以(1)的方式調整以47為根節點的子樹,調整完成後,再分別調整以88和58為根節點的子樹
(3)對整棵樹進行調整,最終大頂堆構建完成
3)對大頂堆進行排序
(1)將大頂堆的第乙個值(整個序列中最大的值)與大頂堆的最後乙個值進行交換。
(2)交換後,最後乙個值作為整個序列中最大值,將此值從大頂堆中剔除,再將剩下的元素再次進行調整為大頂堆。
4、演算法實現
從小到大的排序思路:把一堆數字調整成大頂堆->堆頂元素和末尾元素交換->去掉末尾元素,繼續大頂堆調整->重複以上動作
堆是通過陣列實現的:
1)父結點i的左子節點的位置---(2*i+1)
2)父結點i的右子節點的位置---(2*i+2)
3)子結點i的父結點的位置---floor((i-1)/2) floor函式的作用是向下取整
func heapsort(_ array : inout array)
//2、調整堆結構+交換堆頂元素與末尾元素
for j in (1...(array.count-1)).reversed()
}//調整大頂堆(僅是調整過程,建立在大頂堆以構建的基礎上)
func adjustheap(_ array : inout array, _ i : int, _ length : int)else
//下乙個結點
k = k*2+1
}//將tmp值放到最終的位置
array[i] = tmp
}
5、時間複雜度1)在構建堆的過程中,由於是是完全二叉樹從最下層最右邊非終端節點開始構建,將它與子節點進行比較,對於每個非終端節點而言,最多進行兩次比較和交換操作,因此構建堆的時間複雜度為o(n)
2)在整個排序過程中,第 i 次去堆頂記錄重建堆需要時間為logi ,並且需要取 n - 1次堆記錄,所以重建堆的時間複雜度為o(nlogn)。
3)堆的時間複雜度為o(nlogn)
github**
注:排序的具體實現**在 sortsummary.swift 檔案裡 呼叫是在 viewcontroller.swift
排序演算法 (四)堆排序
對簡單選擇排序的優化。1 將序列構建成大頂堆。2 將根節點與最後乙個節點交換,然後斷開最後乙個節點。3 重複第 一 二步,直到所有節點斷開。堆排序模擬流程圖 public class heapsort 對data陣列從0到lastindex建大頂堆 private static void build...
排序演算法(四)堆排序
堆排序 是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,它是選擇排序的一種。堆的定義 乙個完全二叉樹中,任意父結點總是大於或等於 小於或等於 任何乙個子節點,則為大頂堆 小頂堆 完全二叉樹適合採用順序儲存的方式,因此乙個陣列可以看成乙個完全二叉樹。先將初始檔案r n 建立成乙個大頂堆 小頂堆...
八大排序(四) 堆排序
堆是具有以下性質的完全二叉樹 每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆 每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆 如下圖所示 對堆中的結點按層進行編號,將這種邏輯結構對映到陣列中就是下面這個樣子 以上陣列從邏輯上講就是乙個堆結構,用簡單的公式來描述一下堆的定義就是 大頂堆...