Python實現 《演算法導論 第三版》中的演算法 第6章 堆排序
阿新 • • 發佈:2018-12-15
第6章 堆排序
1. 堆
堆是一個數組,它可以被看成一個近似的完全二叉樹。樹上的每一個結點對應陣列中的一個元素。除最底層外,該樹是完全充滿的,而且是從左向右填充。表示堆的陣列包括兩個屬性:A.length(通常)給出陣列元素的個數,A.heap-size表示有多少堆元素儲存在該陣列中。也就是說,雖然A[1…A.length]可能都存有資料,但只有A[1…A.heap-size]中存放的是堆的有效元素。這裡0<=A.heap-size<=A.length。
下面實現了書中的虛擬碼和練習題,包括:
- P84:計算某一結點的父結點,左孩子和右孩子的下標見前三個函式。
- P86:MAX-HEAPIFY
- P87:練習6.2-5用迴圈控制結構取代遞迴重寫MAX-HEAPIFY,見max_heapify_loop。
- P87:BUILD-MAX-HEAP,採用自底向上的方法利用過程MAX-HEAPIFY把一個大小為n=A.length的陣列A[1…n]轉換為最大堆,而且需要傳入引數heap_size。
- P89:HEAPSORT,堆排序演算法利用BUILD-MAX-HEAP將輸入陣列A[1…n]建成最大堆,其中n=A.length,見heap_sort
def get_parent(i):
return (i-1) // 2
def get_left(i):
return 2 * i + 1
def get_right(i):
return 2 * i + 2
def max_heapify_recursive(A, heap_size, i):
l = get_left(i)
r = get_right(i)
largest_ind = i
if l < heap_size and A[l] > A[largest_ind]:
largest_ind = l
if r < heap_size and A[r] > A[largest_ind]:
largest_ind = r
if largest_ind != i:
A[i], A[largest_ind] = A[largest_ind], A[i]
max_heapify_recursive(A, heap_size, largest_ind)
def max_heapify_loop(A, heap_size, i):
while i < heap_size:
l = get_left(i)
r = get_right(i)
largest_ind = i
if l < heap_size and A[l] > A[largest_ind]:
largest_ind = l
if r < heap_size and A[r] > A[largest_ind]:
largest_ind = r
if largest_ind == i:
break
else:
A[i], A[largest_ind] = A[largest_ind], A[i]
i = largest_ind
def build_max_heap(A, heap_size):
begin = len(A)//2 - 1 # len(A)//2 - 1是堆中第一個葉子節點的前一個節點
for i in range(begin, -1, -1):
max_heapify_loop(A, heap_size, i)
def heap_sort(A):
heap_size = len(A)
build_max_heap(A, heap_size)
for i in range(len(A)-1, 0, -1):
A[0], A[i] = A[i], A[0]
heap_size -= 1
max_heapify_loop(A, heap_size, 0)
def test():
A = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1] # P86例子
max_heapify_recursive(A, len(A), 1)
print(A)
A = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1] # P86例子
max_heapify_loop(A, len(A), 1)
print(A)
B = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] # P88例子
build_max_heap(B, len(B))
print(B)
C = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1] # P89例子
heap_sort(C)
print(C)
if __name__ == '__main__':
test()