堆(Heap)是一个可以被看成近似完全二叉树的数组。树上的每一个节点对应数组的一个元素。除了最底层外,该树是完全充满的,而且是从左到右填充。
- 大顶堆:父节点的值大于等于左右孩子的值
- 小顶堆:父节点的值小于等于左右孩子的值
堆常见的操作:
- createHeap建堆:把一个乱序的数组变成堆结构的数组
- insert:把一个数值放入已经是堆结构的数组中,并保持堆结构
- deleteTop:从大顶堆中取出最大值或从最小堆中取出最小值,并将剩余的数组保持堆结构
- heapSort:借由createHeap和deleteTop对数组进行排序
堆结构的一个常见应用是建立优先队列(Priority Queue)
class Heap:
def __init__(self, n, input_list):
self.n = n # 元素个数
self.maxn = 100 # 元素最大个数
self.heap = [0 for i in range(self.maxn)]
for i in range(1, n+1):
self.heap[i] = input_list[i-1]
def downAdjust(self, low, high):
'''
对heap数组在[low,high]范围进行从上到小调整
low为欲调整节点的数组下标,high一般为堆的最后一个元素的数组下标
'''
i = low # i为欲调整的节点
j = 2*i # j为其左孩子
while j <= high: # 存在孩子节点
if j+1 <= high and self.heap[j+1] > self.heap[j]: # 当右孩子存在且右孩子大于左孩子
j = j+1 # 此时j为右孩子
if self.heap[j] > self.heap[i]: # 孩子中较大值大于父亲节点
self.heap[i], self.heap[j] = self.heap[j], self.heap[i] # 交换
i = j # 继续向下调整
j = 2*i
else:
break
def upAdjust(self, low, high):
i = high # i为待调整节点
j = i//2 # j为其父节点
while j >= low:
if self.heap[j] < self.heap[i]:
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
i = j
j = i//2
else:
break
def createHeap(self):
'''建堆'''
for i in range(self.n//2, 0, -1):
self.downAdjust(i, self.n)
def deleteTop(self):
'''删除堆顶'''
self.heap[1] = self.heap[self.n]
self.n -= 1
self.downAdjust(1, self.n)
def insert(self, x):
'''添加元素'''
self.n += 1
self.heap[self.n] = x
self.upAdjust(1, self.n)
def heapSort(self):
self.createHeap() # 此时堆顶是最大元素
for i in range(self.n, 0, -1):
self.heap[1], self.heap[i] = self.heap[i], self.heap[1]
self.downAdjust(1, i-1)
input_list = [85, 55, 82, 57, 68, 92, 99, 98, 66, 56]
h = Heap(len(input_list), input_list)
h.heapSort()
print(h.heap)