python3-BinaryHeap/二叉堆

参考:https://labuladong.github.io/algo/2/23/65/
感谢大神


二叉堆(以下简称BH)实际就是存储在数组里的完全二叉树。如果某个父节点存储在数组的 i 位置,那么左子节点存储在 i2 位置,右子节点存储在 i2+1 位置。一般0位置不用,从1开始。
二叉堆可以分为最大堆和最小堆,前者指每个父节点的值大于或等于左右子节点的值,所以根节点的值就是整个堆中值最大的;后者类似,指小于或等于。因此,二叉堆的主要应用是:1)堆排序;2)优先级队列。主要方法只有:1)sink(下沉);2)swim(上浮)

这里写了个python3版本。注释都写了

class MaxPQ:
    def __init__(self):
        self.size = 0
        self.pq = [0]

    # 返回当前队列中最大元素
    def max(self):
        return self.pq[1]

    # 交换数组下标i和j的值
    def swap(self, i:int, j:int):
        self.pq[i], self.pq[j] = self.pq[j], self.pq[i]

    # 比较数组下表i和j的值大小
    # 这里暂时用int,别的类型也可以
    def less(self, i:int, j:int)->bool:
        return self.pq[i] < self.pq[j]

    # 获取左子节点的下标
    def left(self, i:int)->int:
        return i * 2

    # 获取右子节点的下标
    def right(self, i:int)->int:
        return i * 2 + 1

    # 获得父节点的下标
    def parent(self, i:int)->int:
        return i // 2

    # 上浮第x个元素
    def swim(self, x:int):
        # 获得父节点下标
        f = self.parent(x)
        # 没有到堆顶且父节点<x
        while x > 1 and self.less(f, x):
            self.swap(f, x)  # 交换位置
            x = f  # 继续向上检查
            f = self.parent(x)

    # 下沉第x个元素
    def sink(self, x:int):
        while self.left(x) <= self.size:
            # 查找左右子节点中较大的值
            m = self.left(x)
            r = self.right(x)
            # 如果右子节点存在且比左子节点大,那么修改m
            if r <= self.size and self.less(m, r):
                m = r
            # 如果x比俩子节点都大,那么下沉结束
            if self.less(m, x): break
            # 否则交换x和m,继续检查
            self.swap(x, m)
            x = m

    # 插入元素
    def insert(self, x):
        self.size += 1
        # 放到数组末尾
        self.pq.append(x)
        # 通过swim检查
        self.swim(self.size)

    # 删除最大元素
    def delMax(self):
        m = self.pq[1]
        self.swap(1, self.size)
        del self.pq[self.size]
        self.size -= 1
        self.sink(1)
        return m

    def print(self):
        print("size:" + str(self.size) + "[" + ",".join([str(i) for i in self.pq]) + "]")

t = MaxPQ()
t.insert(2)
t.print()
t.insert(3)
t.insert(1)
t.print()
t.insert(8)
t.print()
t.insert(6)
t.print()
print(t.delMax())
t.print()
t.insert(-2)
t.print()

'''
输出结果:
size:1[0,2]
size:3[0,3,2,1]
size:4[0,8,3,1,2]
size:5[0,8,6,1,2,3]
8
size:4[0,6,3,1,2]
size:5[0,6,3,1,2,-2]

'''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值