將初始待排序關鍵字序列(r1,r2....rn)構建成大頂堆,此堆為初始的無序區
將堆頂元素r[1]與最後乙個元素r[n]交換,此時得到新的無序區(r1,r2,......rn-1)和新的有序區(rn)
由於交換後新的堆頂r[1]可能違反堆的性質,因此需要對當前無序區(r1,r2,......rn-1)調整為新堆,然後再次將r[1]與無序區最後乙個元素交換,得到新的無序區(r1,r2....rn-2)和新的有序區(rn-1,rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成
下圖來張教材的圖,是整個堆排序的過程: 整個過程的核心就是先初始化大頂堆,將最大數(堆頂)的放到堆的最後乙個, 堆長度-1, 繼續調整成大頂堆,直至有序序列為len(array_list)-1.
堆排序前42是在42後面,排序後42在42前面,因此堆排序是不穩定的。
給定乙個列表array=[16,7,3,20,17,8],對其進行堆排序。
首先根據該陣列元素構建乙個完全二叉樹,得到
然後需要構造初始堆,則從最後乙個非葉節點開始調整,調整過程如下:
第一步: 初始化大頂堆(從最後乙個有子節點開始往上調整最大堆)
20和16交換後導致16不滿足堆的性質,因此需重新調整
第二步: 堆頂元素r[1]與最後乙個元素r[n]交換,交換後堆長度減一
即每次調整都是從父節點、左孩子節點、右孩子節點三者中選擇最大者跟父節點進行交換(交換之後可能造成被交換的孩子節點不滿足堆的性質,因此每次交換之後要重新對被交換的孩子節點進行調整)。有了初始堆之後就可以進行排序了。
第三步: 重新調整堆。此時3位於堆頂不滿堆的性質,則需調整繼續調整(從頂點開始往下調整)
重複上面的步驟:
注意了,現在你應該了解堆排序的思想了,給你一串列表,你也能寫出&說出堆排序的過程。
在寫演算法的過程中,剛開始我是很懵比。後來終於看懂了。請特別特別注意: 初始化大頂堆時 是從最後乙個有子節點開始往上調整最大堆。而堆頂元素(最大數)與堆最後乙個數交換後,需再次調整成大頂堆,此時是從上往下調整的。
不管是初始大頂堆的從下往上調整,還是堆頂堆尾元素交換,每次調整都是從父節點、左孩子節點、右孩子節點三者中選擇最大者跟父節點進行交換,交換之後都可能造成被交換的孩子節點不滿足堆的性質,因此每次交換之後要重新對被交換的孩子節點進行調整。我在演算法中是用乙個while迴圈來解決的。
def sift_down(arr, start, end):
root = start
while true:
# 從root開始對最大堆調整
child = 2 * root + 1
if child > end:
break
# 找出兩個child中交大的乙個
if child + 1 <= end and arr[child] < arr[child + 1]:
child += 1
if arr[root] < arr[child]:
# 最大堆小於較大的child, 交換順序
arr[root], arr[child] = arr[child], arr[root]
# 正在調整的節點設定為root
root = child
else:
# 無需調整的時候, 退出
break
def heap_sort(arr):
# 從最後乙個有子節點的孩子還是調整最大堆
first = len(arr) // 2 - 1
for start in range(first, -1, -1):
sift_down(arr, start, len(arr) - 1)
# 將最大的放到堆的最後乙個, 堆-1, 繼續調整排序
for end in range(len(arr) -1, 0, -1):
arr[0], arr[end] = arr[end], arr[0]
sift_down(arr, 0, end - 1)
def main():
# [7, 95, 73, 65, 60, 77, 28, 62, 43]
# [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
l = [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
print l
heap_sort(l)
print l
if __name__ == "__main__":
array = [16, 7, 3, 20, 17, 8]
print(array)
heap_sort(array)
print(array)
python3堆排序 python 堆排序
堆排序 堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆積是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點 但是不保證所有左子樹比右子樹小反之亦然 堆排序可以說是一種利用堆的概念來排序的選擇排序。分為兩種方法 大頂堆 每個...
堆排序演算法之python3實現
堆排序 向下調整的函式,傳入的資料為堆,堆頂節點的編號和堆末尾的界限值 defheapify heap,start,end father start son father 2 son儲存較大的子節點的編號,初始化為左子節點 while end son 當目前資料所處的節點還有子節點時,繼續迴圈調整 ...
堆排序python3實現
堆排序的思想 先將無序陣列調整為大頂堆 小頂堆,然後將堆頂元素r0和最後乙個孩子節點rn交換位置,此時r0 rn 1是無序的,rn是有序的,繼續迭代,將r0 rn 1調整為大頂堆 小頂堆,然後將堆頂元素r0和rn 1交換位置,迭代到堆中只剩下乙個元素為止 def heapfiy nums,n,i l...