通过完全二叉树构建堆:(索引为 i的节点,左子树和右子树分别是2i+1和2i+2)
1.push 的时候,将元素加入到末尾,通过_heapify_up 进行调整(和父节点比较大小)
2.pop 的时候,交换堆顶元素和末尾元素,通过_heapify_down 进行调整(和左右子树比较大小)
class Heap:
def __init__(self):
self.heap=[]
def _heapify_up(self):
#末尾元素向上调整,只需要不断和父节点进行比较就行
#考虑2i+1, 2i+2 -> i,父节点的索引是 (index-1)//2
idx= len(self.heap)-1
while idx:#向上调整,直到idx=0也就是堆顶
parent_idx=(idx-1)//2
if self.heap[parent_idx]<self.heap[idx]:
self.heap[parent_idx],self.heap[idx]= self.heap[idx],self.heap[parent_idx]
idx=parent_idx
continue
break #说明self.heap[parent_idx]>=self.heap[idx]
def _heapify_down(self):
#堆顶元素向下调整,只需要不断和左、右子树进行比较就行
i=0
n=len(self.heap)
while 2*i+1<n:
left=2*i+1
right=2*i+2
if self.heap[left]<=self.heap[i]:#左子树小于等于根,可能无需调整,看下右子树是否存在且大于根
if right<n and self.heap[right]>self.heap[i]:
self.heap[i],self.heap[right]=self.heap[right], self.heap[i]
i=right
else:#无需调整,则提前结束循环
break
else:#左子树大于根,则必然需要调整,只是还需要看右子树是否存在且大于左子树
if right<n and self.heap[right]>self.heap[left]:
self.heap[i],self.heap[right]=self.heap[right], self.heap[i]
i=right
else:
self.heap[i],self.heap[left]=self.heap[left], self.heap[i]
i=left
def push(self,x):#入堆之后,需要进行调整
self.heap.append(x)
self._heapify_up()
def pop(self):#弹出堆顶元素之后,需要进行调整
print(self.heap[0])
#adjust:先交换堆顶元素和最末尾的元素,弹出末尾元素
self.heap[0],self.heap[-1]=self.heap[-1], self.heap[0]
self.heap.pop()
self._heapify_down()
def top(self):
print(self.heap[0])
n=int(input())
h=Heap()
for _ in range(n):
op=input().split()
if op[0]=='push':
h.push(int(op[1]))
elif not h.heap:#堆为空的情况下,直接输出"empty"
print('empty')
elif op[0]=='top':
h.top()
else: #op[0]=='pop':
h.pop()

京公网安备 11010502036488号