max-heapify(a, i)
1 l← left(i)
2 r← right(i)
3ifl≤heap-size[a] and a[l] >
a[i]
4thenlargest←l
5elselargest←i
6ifr≤heap-size[a] and a[r] >
a[largest]
7thenlargest←r
8iflargest≠i
9thenexchange a[i]↔a[largest]
10max-heapify(a, largest)
build-max-heap(a)
1heap-size[a] ←
length[a]
2fori←⌊length
[a]/2
⌋downto1
3domax-heapify(a, i)
heapsort(a)
1 build-max-heap(a)
2fori←length[a]downto2
3doexchange a[1]↔a[i]
4heap-size[a] ←
heap-size[a] - 1
5max-heapify(a, 1)
初始化:首先,對於第一輪迭代開始之前,最大堆已經建好,
a[1]
陣列儲存最大值。
保持:接下來,我們來考慮第二個性質:證明每一輪迴圈都能使迴圈不變式保持成立。在
for迴圈
2~5行的迭代開始時,子陣列
a[1..i]
是乙個包含了乙個
a[1..n]中的i
個最小元素的最大堆;而子陣列
a[i+1..n]
包含了已經排序的
n-i個最大元素。
當i=k
時,這時對應
a[1]
是剩餘陣列的最大值,先交換
a[1]
和a[k]
中的值,那麼交換後,
a[1]
很有可能不是剩餘陣列
a[1..k-1]
中的最大值,這時呼叫
max-heapify(a, 1)
,因為在呼叫前,除了根節點外,都是符合最大堆的要求,呼叫
max-heapify(a, 1)
子過程可以保證在這種情況下把這個放於根節點的小元素調整到合適位置,而保持
a[1..k-1]
仍然是最大堆。(調整的部分符合最大堆規則,沒有調整的部分也符合最大堆規則,因此可以保證)另外,
a[1..k-1]
是陣列中最小的
k-1個元素。而子陣列
a[k…n]
包含了已排序的
n-k+1
個元素。這樣就證明了每一輪迴圈都能使迴圈不變式保持成立。
終止:最後,分析一下迴圈結束時的情況。對於堆排序,當i等於
1時,迴圈結束。在迴圈不變式中,那麼意味著
a[2..n]
子陣列包含了原來陣列的最大的
n-1個元素,且已經排序完成。而
a[1]
是a[1..n]
中的最小元素,因此,整個陣列就排序好了,這意味著演算法是正確的。
build-max-heap(a)
的時間代價是
o(n)
max-heapify(a, 1)
的時間代價是
o(lgn)
所以時間代價的上界是
o(nlgn)
堆排序 《演算法導論》學習筆記六
堆排序就是將一組數按二叉樹層序遍歷的儲存順序,經過一系列比較轉移,最終變成有序的陣列,這裡的二叉樹堆一定是完全二叉樹。堆排序能進行的基礎是有個最大堆的陣列,最大堆性質是指樹上的每個節點的子節點都比自己小或等於。因此最頂上的根節點一定是值最大的節點,有了最大堆在,堆排序就可以進行了,從層序遍歷的最後乙...
堆排序 演算法導論
python版 1 defheapsort input 2output 3buildheap input 4print input 5while input 6i len input 1 7input 0 input i input i input 0 89 ifinput 10maxheapify...
堆排序 演算法導論
python版 1 defheapsort input 2output 3buildheap input 4print input 5while input 6i len input 1 7input 0 input i input i input 0 89 ifinput 10maxheapify...