堆排序算法以及python實現


堆滿足的條件:1,是一顆完全二叉樹。2,大根堆:父節點大於各個孩子節點。每個節點都滿足這個道理。小根堆同理。

parent = (i-1)/2    #i為當前節點

left = 2*i+1

right = 2*i + 2

堆可以分為大根堆和小根堆,這里用大根堆的情況來定義操作:
(1)大根堆調整(max_heapify):
將堆的末端子節點作調整,使得子節點永遠小於父節點。這是核心步驟,在建堆和堆排序都會用到。
比較i的根節點和與其所對應i的孩子節點的值,當i根節點的值比左孩子節點的值要小的時候,就把i根節點和左孩子節點所對應的值交換,同理,就把i根節點和右孩子節點所對應的值交換。
然后再調用堆調整這個過程,可見這是一個遞歸的過程。

def max_heapify(heap,heapSize,root): # 調整列表中的元素並保證以root為根的堆是一個大根堆
'''
給定某個節點的下標root,這個節點的父節點、左子節點、右子節點的下標都可以被計算出來。
父節點:(root-1)//2
左子節點:2*root + 1
右子節點:2*root + 2 即:左子節點 + 1
'''
left = 2*root + 1
right = left + 1
larger = root
if left < heapSize and heap[larger] < heap[left]:
larger = left
if right < heapSize and heap[larger] < heap[right]:
larger = right
if larger != root: # 如果做了堆調整則larger的值等於左節點或者右節點的值,這個時候做堆調整操作
heap[larger], heap[root] = heap[root], heap[larger]
# 遞歸的對子樹做調整
max_heapify(heap, heapSize, larger)

(2)建立大根堆(build_max_heap):
將堆中所有的數據重新排序。建堆的過程其實就是不斷做大根堆調整的過程,從(heapSize -2)//2處開始調整,一直調整到第一個根節點。

def build_max_heap(heap): # 構造一個堆,將堆中所有數據重新排序
heapSize = len(heap)
for i in range((heapSize -2)//2,-1,-1): # 自底向上建堆
max_heapify(heap, heapSize, i)

(3)堆排序(heap_sort):
將根節點取出與最后一位做對調,並做最大堆調整的遞歸運算。堆排序是利用建堆和堆調整來進行的。
首先建堆,然后將堆的根節點選出與最后一個節點進行交換,然后將前面len(heap)-1個節點繼續做堆調整,直到將所有的節點取出,對於有n個元素的一維數組我們只需要做n-1次操作。

import random

def heap_sort(heap): # 將根節點取出與最后一位做對調,對前面len-1個節點繼續進行堆調整過程。
build_max_heap(heap)
# 調整后列表的第一個元素就是這個列表中最大的元素,將其與最后一個元素交換,然后將剩余的列表再遞歸的調整為最大堆
for i in range(len(heap)-1, -1, -1):
heap[0], heap[i] = heap[i], heap[0]
max_heapify(heap, i, 0)

# 測試
if __name__ == '__main__':
a = [30, 50, 57, 77, 62, 78, 94, 80, 84]
print(a)
heap_sort(a)
print(a)
b = [random.randint(1,1000) for i in range(1000)]
print(b)
heap_sort(b)
print(b)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM