話不多說,看**。參考鏈結
def
build_max_heap
(heap)
:# 構造乙個堆,將堆中所有資料重新排序
heapsize =
len(heap)
for i in
range
((heapsize -2)
//2,-
1,-1
):# 自底向上建堆
max_heapify(heap, heapsize, i)
defmax_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)
defheap_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)
import heapq
# 測試
if __name__ ==
'__main__'
: a =[30
,50,57
,94,80
,84,77
,62,78
]print
(a) heap_sort(a)
print
(a) b = a[:]
heapq.heapify(b)
print
(b) res =
for i in
range
(len
(a)):)
print
(res)
好了。
時間複雜度
堆排序的時間複雜度分為兩個部分乙個是建堆的時候所耗費的時間,乙個是進行堆調整的時候所耗費的時間。而堆排序則是呼叫了建堆和堆調整。
剛剛在上面也提及到了,建堆是乙個線性過程,從len/2-0一直呼叫堆調整的過程,相當於o(h1)+o(h2)+…+o(hlen/2)這裡的h表示節點深度,len/2表示節點最大深度,對於求和過程,結果為線性的o(n) 。
堆調整為乙個遞迴的過程,調整堆的過程時間複雜度與堆的深度有關係,相當於lgn的操作。
因為建堆的時間複雜度是o(n),調整堆的時間複雜度是o(lgn),所以堆排序的時間複雜度是o(nlgn)。
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...
排序演算法 堆排序
花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...
排序演算法 堆排序
由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...