堆排序演算法講解 及python3實現

2021-08-28 08:26:23 字數 3005 閱讀 5577

將初始待排序關鍵字序列(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...