完全二叉树
一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
完全二叉树判定算法思路
判断一棵树是否是完全二叉树的思路:
- 如果树为空,则直接返回错
- 如果树不为空:层序遍历二叉树
- 如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列;
- 如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树;
- 如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树;
堆(heap)
又被为优先队列(priority queue)。尽管名为优先队列,但堆并不是队列。
堆需要满足的条件:
1. 必须是二叉树,且必须是完全二叉树
2. 各个父节点必须大于或小于左右结点, 其中最顶层的根结点必须是最大或者最小的
1.最大堆的实现
1.初始化堆
堆可以使用list实现,就是按照层序遍历顺序将每个节点上的值存放在数组中。
parent = i, # i 从 0 开始
left = 2 * i + 1
right = 2 * i + 2
2.在堆中增加元素
3.删除根节点,并重建堆结构
# 最大堆的实现 class MaxHeap(): def __init__(self, maxSize=None): self.maxSize = maxSize self.li = [None] * maxSize self.count = 0 def length(self): # 求数组的长度 return self.count def show(self): if self.count <= 0: print('null') else: print(self.li[: self.count]) def add(self, value): if self.count >= self.maxSize: # 判断是否数组越界 raise Exception('full') self.li[self.count] = value # 将新节点增加到最后 self._shift_up(self.count) # 递归构建大堆 self.count += 1 def _shift_up(self, index): # 往大堆中添加元素,并保证根节点是最大的值: # 1.增加新的值到最后一个结点,在add实现; 2.与父节点比较,如果比父节点值大,则交换 if index > 0: parent = (index - 1) // 2 # 找到根节点 if self.li[index] > self.li[parent]: # 交换结点 self.li[index], self.li[parent] = self.li[parent], self.li[index] self._shift_up(parent) # 继续递归从底往上判断 def extract(self): # 弹出最大堆的根节点,即最大值 # 1.删除根结点,将最后一个结点作为更结点 ; 2.判断根结点与左右结点的大小,交换左右结点较大的 if not self.count: raise Exception('null') value = self.li[0] self.count -= 1 self.li[0] = self.li[self.count] # 将最后一个值变为第一个 self._shift_down(0) return value def _shift_down(self, index): # 1.判断是否有左子节点并左大于根,左大于右;2.判断是否有右子节点,右大于根 left = 2 * index + 1 right = 2 * index + 2 largest = index # 判断条件 if left < self.length() and self.li[left] > self.li[largest]: largest = left if right < self.length() and self.li[right] > self.li[largest]: largest = right if largest != index: # 将 两者交换 self.li[index], self.li[largest] = self.li[largest], self.li[index] self._shift_down(largest) import numpy as np m = MaxHeap(10) np.random.seed(123) num = np.random.randint(100, size=10) # 创建随机的10个数 print(m.length()) for i in num: m.add(i) m.show() print(m.length()) for i in range(5): print(m.extract(), end=' ,')