最小堆-Python代码实现

前言

好久没写博客了,这篇内容还是很久之前就写好的,现在想想还是把它贴出来吧,也算是贡献一点代码。
另外想直接获取代码的直接拷贝即可,分析过程写的不是很有逻辑性,大家将就着看吧。

分析过程

最小堆和最大堆结构图如下:
在这里插入图片描述
堆需要满足的条件:

  1. 必须是二叉树,且必须是完全二叉树

  2. 各个父节点必须大于或小于左右结点, 其中最顶层的根结点必须是最大或者最小的

实现这样的堆可以采用list或者数组来实现,将这样的二叉树以层序遍历存储在数组中,对于这个list或者数组中的第K个节点其:

  • 父节点的下标为:parent = (k-1)/2
  • 左子节点下标为: left = k*2 + 1
  • 右子节点下标为: right = k*2 + 2

其对应的关系如下图:
在这里插入图片描述
在堆中添加一个元素,将新加入的元素放到队尾,然后改变树的结构:
在这里插入图片描述
弹出根元素,把最后一个元素移到根节点,然后改变树的结构:
在这里插入图片描述

代码实现

class minheap:
    def __init__(self, item=[]):
        # 初始化。item为数组 可以存放结构体 只不过后面进行数值比较时需要加上相应的引用
        self.items = item
        self.len = len(self.items)
        
    def min_heap(self, k):
        #最小堆化 使得以k为根节点的子树变成最小堆 前提是其下面的所有子树都已经是最小堆了
        left = k*2+1
        right = k*2+2 #获取k的左右子节点 数组按照层序遍历存储 其左右子节点的计算方式就是这样
        mink = k
        if left < self.len and self.items[left]<self.items[mink]:#如果左子节点存在 并且比父节点小 则应该交换一下 先记录下来
            mink = left
        if right < self.len and self.items[right]<self.items[mink]:
            mink = right
        if mink != k:#如果找到了比父节点还小的值 那就把最小值和其进行交换
            self.items[k],self.items[mink] = self.items[mink],self.items[k]
            self.min_heap(mink)#然后把第mink节点改变了 所以得把以这个节点为父节点的子树递归成最小堆
        # 如果当前节点都小于其左右子节点 则无需进行交换 
        
    def build_min_heap(self):
        #创建初始化的最小堆 从最下面一层的最右边的一个子节点的父节点进行遍历
        last_node = self.len-1
        last_pa = int((last_node-1)/2 )#第k个节点的父节点计算方式
        while last_pa >= 0:
            self.min_heap(last_pa)
            last_pa -=1
    def get_min(self):#获取当前最小的值 不会对其有影响
        if len(self.items)>0:
            return self.items[0]
        else:
            return None
    def pop(self):#弹出栈顶 最小值 然后把最后一个节点移动到栈顶 再对其进行最小堆化
        if len(self.items)>0:
            val = self.items[0]
            self.items[0] = self.items[-1]
            self.items.pop()
            self.len = len(self.items)
            self.min_heap(0)
            return val
        else:
            None
    def add(self,k):#向堆里添加新的元素
        self.items.append(k)#将新元素加入到栈尾 然后重新对整个进行最小堆化
        self.len = len(self.items)
        last = self.len -1
        last_pa = int((last-1)/2 )#第k个节点的父节点计算方式
        while last_pa >= 0:
            if self.items[last_pa]<=self.items[last]:#如果最后一个节点的父节点的值已经满足条件 则无需调整树的结构
                break
            else :#否则需要将两个节点的值互换 然后向上 
                self.items[last_pa],self.items[last] =  self.items[last],self.items[last_pa]
                last = last_pa
                 #此时以last为父节点的子树一定满足最小堆的条件了 但是其父节点不一定满足条件 因此需要向上判断
                last_pa = int((last-1)/2 )
        
a = []
k = minheap(a)
k.build_min_heap()
print(k.items)
print(k.pop())
print(k.items)
k.add(1)
print(k.items)
k.add(10)
print(k.items)

Notes:

博客中的图都是直接拷贝的另一博客的,当时忘了记下链接了,如有侵权,请通知删除。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值