优先队列出队跟队列一样,从队首出队;但队内的次序由优先级决定,即优先级高的数据项可以插队,排到前面。
二叉堆能够将优先队列的入队和出队复杂度都保持在O(logn)
完全二叉树,如果用顺序表来表示的话,设根节点下标为1,若某节点下标为p,则其左子节点下标为2p,右子节点下标为2p+1,父节点下标为p//2.
最小二叉堆代码:
class BinaryHeap:
def __init__(self):
self.heapList=[0] #用0占位,使得下标从1开始
self.currentSize=0
def percUp(self,i): #上浮,跟父节点比大小
while i//2>0:
if self.heapList[i] < self.heapList[i//2]:
self.heapList[i],self.heapList[i//2]=self.heapList[i//2],self.heapList[i]
else:
break #如果没有父节点大,则无需继续上浮比较
i//=2
def insert(self,item):
self.heapList.append(item)
self.currentSize+=1
self.percUp(self.currentSize)
def percDown(self,i): #下沉,若大于子节点,则每次跟子节点中最小的进行交换
while 2*i<=self.currentSize: #若还有子节点
if 2*i+1<=self.currentSize: #如果右节点还存在
minIndex=2*i if self.heapList[2*i]<self.heapList[2*i+1] else 2*i+1
else: #右节点不存在
minIndex=2*i
if self.heapList[i]>self.heapList[minIndex]:
self.heapList[i],self.heapList[minIndex]=self.heapList[minIndex],self.heapList[i]
i=minIndex
else:
break
def delMin(self): #移走根节点,之后为了保持完全二叉树的结构,需要把最后一个数据项补到根节点,之后再进行下沉操作
minVal=self.heapList[1]
self.heapList[1]=self.heapList[self.currentSize]
self.heapList.pop()
self.currentSize-=1
self.percDown(1)
return minVal
def buildHeap(self,alist):
self.heapList=[0]+alist
self.currentSize=len(alist)
i=self.currentSize//2 #从最后一个节点的父节点开始下沉
while i>0:
self.percDown(i)
i-=1
return self.heapList
r=BinaryHeap()
alist=[1,6,4,5,3,8,9,0]
print(r.buildHeap(alist))
r.delMin()
print(r.heapList)
r.insert(2)
print(r.heapList)
输出
[0, 0, 1, 4, 5, 3, 8, 9, 6]
[0, 1, 3, 4, 5, 6, 8, 9]
[0, 1, 2, 4, 3, 6, 8, 9, 5]