堆的定義,n個關鍵字序列l[1...n]稱為堆,當且僅當序列滿足:
1. l[i]≥l[2i] 且 l[i]≥l[2i+1](大根堆)
2. l[i]≤l[2i]且l[i]≤l[2i+1] (小根堆)
i需要滿足的特點為(1≤i≤⌊n/2⌋)
可以將一維陣列視為一棵完全二叉樹,滿足條件1的堆稱為大根堆,大根堆的最大元素存放在根結點,且其任一非根結點的值小於等於其雙親結點值。滿足條件2的堆稱為小根堆,小根堆的根節點是最小值,且其任一非根結點的值大於等於其雙親結點值。
大根堆:
對於所有具有雙親結點含義編號從大到小(⌊n/2⌋~1)做出如下調整:
若孩子結點皆小於雙親結點,則該結點的調整結束。若存在孩子結點大於雙親結點,則將最大的孩子結點與雙親結點交換,並該孩子結點進行同樣的交換,知道孩子結點為葉子結點為止。堆排序首先將存放在l[1...n]中的n個元素建成初始堆,由於堆本身的特點(以大根堆為例),堆頂元素就是最大值。輸出堆頂元素後,通常將堆底元素送入堆頂,此時根結點已不滿足大根堆的性質,堆被破壞,將堆頂元素向下調整令其繼續保持大頂堆的性質,再輸出堆頂元素。如此重複,直到堆中僅剩乙個元素為止。
堆排序需要解決的問題:
如何將無序序列構造成初始堆。輸出堆頂元素後,如何將剩下元素調整成新的堆。
堆排序的關鍵是構造初始堆,n個結點的完全二叉樹,最後的乙個結點是第n/2個結點的孩子結點。對第n/2個結點為根的子樹篩選(對於大根堆,若根結點的關鍵字小於左右孩子中關鍵字較大值,則交換),使得該子樹成為堆。之後向前依次對各結點([n/2] - 1 ~ 1)為根的子樹進行篩選,看該結點是否大於其左右子節點的值,若不大於,則將左右子結點中的較大值與之交換,交換後可能會破壞下一級的堆,於是繼續採用上述方法構造下一級的堆。直到以該結點為根的子樹構成堆為止。反覆利用上述調整堆的方法建堆,直到根結點。
如圖:初始時調整l[4]子樹,將09與32交換,交換後滿足堆的定義;向前繼續調整l[3]子樹,78小於左右孩子的較大者87,交換,交換後滿足堆的定義;向前繼續調整l[2]子樹,17小於左右孩子的較大者45,交換後滿足堆的定義;向前調整至根結點l[1],53 < 左右孩子的較大者87,交換,交換後破壞了l[3]子樹的堆,採用上述方法堆l[3]進行調整,53 < 左右孩子的較大者78,交換,至此該完全二叉樹滿足堆的定義。
輸出堆頂元素後,將堆的最後乙個元素與堆頂元素交換,此時堆的性質被破壞,需要向下進行篩選。將09和左右孩子的較大者78進行交換,交換後破壞了l[3]子樹的堆,繼續對l[3]子樹向下篩選,將09和左右孩子較大者65交換,交換後得到新堆。
}**結果:
演算法最好時間
最壞時間
平均時間
額外空間/空間複雜度
穩定性堆排序o(nlog2^n)
o(nlog2^n)
o(nlog2^n)
o(1)
不穩定空間效率:僅使用常數個輔助單元,所以空間時間複雜度為o(1)。
時間效率:建堆的時間為o(n),之後有n-1此向下調整操作,每次調整的時間複雜度為o(log2^n),故在最好,最壞和平均情況下,堆排序的時間複雜度為o(nlog2^n)。
穩定性:進行篩選時,有可能把後面相同關鍵字的元素調整到前面,所以堆排序演算法是一種不穩定的排序方法。表l=
構造初始堆時可能將2交換到堆頂,此時l=,最終排序序列為l=,由此可知,堆排序是一種不穩定的排序。
選擇排序之堆排序
include includevoid swap int data,int i,int j 優美的遞迴實現堆調整 void adjustbigtopheap int data,int root,int n max root,意味著左孩子或右孩子大於父節點的值 即根為root的二叉樹的大頂堆性質被破壞...
選擇排序之堆排序
1 堆排序是利用堆這種資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為o nlogn 它也是不穩定排序。2 堆是具有以下性質的完全二叉樹 每個結點的值都大於或等於其左右孩子節點的值,稱為大頂堆,注意 沒有要求節點的左孩子的值和右孩子的值的大小關係。3 每個節點...
選擇排序之堆排序
堆排序 heapsort 是利用堆積樹這種資料結構所設計的一種排序演算法,他是選擇排序的一種,其儲存結構類似於完全二叉樹 二叉堆滿足的性質 1父節點的值總是大於或者等於 小於或者等於 孩子節點的值的 2.每個節點的 左右子樹都是乙個二叉堆。當父節點的值大於或者等於任意乙個子結點的值時,則成為大根堆 ...