树的应用3—二叉堆
2020-06-01 本文已影响0人
腹黑君
二叉堆实现优先队列
定义:优先队列,优先级高的放在队首,优先级低的放在队尾,优先级高的先出队。
-
复杂度分析:
可将入队与出队的复杂度都保持在O(logN),排序复杂度为O(NlogN)
对比正常用有序表实现入队与出队的操作,入队的复杂度为O(1~N),出队的复杂度为O(N) -
采用方法:完全二叉树
完全二叉树: 最底层的叶节点都集中在最左,内部节点都有两个子节点,最多有一个节点例外。
image.png
满二叉树:所有的内部节点都有左右两个子节点。特殊的完全二叉树
-
方法特点:
①采用完全二叉树来实现对数复杂度。
②节点若为N,左子节点为2N,右子节点为2N+1
③堆次序:从叶节点至根节点的次序是从大到小排好次序的结构。
④实际是用一个列表来表示二叉堆的次序。
⑤新节点加入为叶节点,并逐步上浮
⑥最小节点出队,将最后一项提至根节点,并逐级下沉;未排序的堆列表也通过逐级下沉,获得排序好的二叉堆
# -------------------最小二叉堆的实现--------------------
class BinHeap:
def __init__(self):
# 设置一个下标0占位但不用,根节点从1开始
self.heapList = [0]
self.currentSize = 0
def insert(self,key):
self.heapList.append(key)
self.currentSize += 1
# 新节点加入,从叶节点加入,调整次序,逐步上浮,与各级父节点比较
self.percup(self.currentSize)
def minchild(self, i):
if i*2 + 1 > self.currentSize:
# 如果只有一个子节点,就只能与该子节点下沉
return i*2
elif self.heapList[i*2 + 1] > self.heapList[i*2]:
# 从较小的子节点下沉
return i*2
else:
return i*2 + 1
def percup(self, i):
while i//2 > 0:
if self.heapList[i] < self.heapList[i//2]:
tmp = self.heapList[i//2]
self.heapList[i//2] = self.heapList[i]
self[i] = tmp
i = i//2
def perDown(self, i):
while i*2 <= self.currentSize:
div_num = self.minchild(i)
if self.heapList[i] > self.heapList[div_num]:
tmp = self.heapList[i]
self.heapList[i] = self.heapList[div_num]
self.heapList[div_num] = tmp
i = div_num
# 删除最小的节点,即将最底层的节点值赋予根节点,同时删除最底层节点,调整次序,逐步下沉,与各级子节点比较
def delMin(self):
reval = self.heapList[1]
self.heapList[1] = self.heapList[self.currentSize]
self.currentSize -= 1
self.heapList.pop()
self.percDown(1)
return reval
# 直接对无序表进行下沉,从倒数第二层开始逐层进行下沉
def buildHeap(self,alst):
i = len(alst) // 2
self.currentSize = len(alst)
self.heapList = [0] + alst[:]
print(self.heapList, i)
while i > 0:
self.perDown(i)
i -= 1
print(self.heapList, i)