python3 堆

完全二叉树

一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

完全二叉树判定算法思路

判断一棵树是否是完全二叉树的思路:

  1. 如果树为空,则直接返回错
  2. 如果树不为空:层序遍历二叉树
    1. 如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列;
    2. 如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树;
    3. 如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树;

堆(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=' ,')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值