介紹
堆排序在 top K 問題中使用比較頻繁。堆排序是採用二叉堆的數據結構來實現的,雖然實質上還是一維數組。二叉堆是一個近似完全二叉樹 。
二叉堆具有以下性質:
- 父節點的鍵值總是大於或等於(小於或等於)任何一個子節點的鍵值。
- 每個節點的左右子樹都是一個二叉堆(都是最大堆或最小堆)。
步驟
- 構造最大堆(Build_Max_Heap):若數組下標範圍爲0~n,考慮到單獨一個元素是大根堆,則從下標n/2開始的元素均爲大根堆。於是只要從n/2-1開始,向前依次構造大根堆,這樣就能保證,構造到某個節點時,它的左右子樹都已經是大根堆。
- 堆排序(HeapSort):由於堆是用數組模擬的。得到一個大根堆後,數組內部並不是有序的。因此需要將堆化數組有序化。思想是移除根節點,並做最大堆調整的遞歸運算。第一次將heap[0]與heap[n-1]交換,再對heap[0…n-2]做最大堆調整。第二次將heap[0]與heap[n-2]交換,再對heap[0…n-3]做最大堆調整。重複該操作直至heap[0]和heap[1]交換。由於每次都是將最大的數併入到後面的有序區間,故操作完後整個數組就是有序的了。
- 最大堆調整(Max_Heapify):該方法是提供給上述兩個過程調用的。目的是將堆的末端子節點作調整,使得子節點永遠小於父節點 。
代碼
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 27 11:53:24 2016
@author: zang
"""
from matplotlib import pyplot as plt
import random
def heapSort(ary) :
n = len(ary)
first = int(n/2-1) #最後一個非葉子節點
for start in range(first,-1,-1) : #構造大根堆
max_heapify(ary,start,n-1)
for end in range(n-1,0,-1): #堆排,將大根堆轉換成有序數組
ary[end],ary[0] = ary[0],ary[end]
max_heapify(ary,0,end-1)
return ary
#最大堆調整:將堆的末端子節點作調整,使得子節點永遠小於父節點
#start爲當前需要調整最大堆的位置,end爲調整邊界
def max_heapify(ary,start,end):
root = start
while True :
child = root*2 +1 #調整節點的子節點
if child > end : break
if child+1 <= end and ary[child] < ary[child+1] :
child = child+1 #取較大的子節點
if ary[root] < ary[child] : #較大的子節點成爲父節點
ary[root],ary[child] = ary[child],ary[root] #交換
root = child
else :
break
def plotScatter(inputList):
plt.scatter(range(len(inputList)),inputList)
plt.show()
if __name__ == "__main__":
num_list = range(1000)
unsortedList = random.sample(num_list, 30)
print "unsortedList:"
plotScatter(unsortedList)
print unsortedList
sortedList = heapSort(unsortedList)
print "sortedList:"
plotScatter(sortedList)
print sortedList
測試
輸入
[796, 311, 58, 512, 470, 568, 648, 272, 132, 813, 284, 652, 887, 727, 709, 867, 206, 562, 287, 295, 805, 336, 51, 416, 799, 967, 760, 596, 161, 131]
輸出
[51, 58, 131, 132, 161, 206, 272, 284, 287, 295, 311, 336, 416, 470, 512, 562, 568, 596, 648, 652, 709, 727, 760, 796, 799, 805, 813, 867, 887, 967]
分析
情況 | 性能 |
---|---|
Worst case performance: | |
Best case performance: | |
Average case performance: | |
Worst case space complexity: |