Binary Heap 二叉堆 (二)

一、二叉堆

       二叉堆本质上是一种完全二叉树

       它分为两类:最大堆和最小堆。最大堆的任何一个父节点的值都大于或等于它左右孩子节点的值;最小堆的任何一个父节点的值,都小于或等一它左右孩子节点的值。

      二叉堆虽然是一个完全二叉树,但它的存储方式并不是链式存储,而是顺序存储。换句话说,二叉堆的所有节点都存储在数组中。

假设"第一个元素"在数组中的索引为i,则父节点和子节点的位置关系如下:

索引为i的父节点的下标:(i-1)/2

索引为i的左孩子的下标:2*i+1

索引为i的右孩子的下标:2*i+2

二、二叉堆操作

1、添加节点

1、新元素一律先插入到堆的尾部

2、依次向上调整整个堆的结构(一直到根即可)

 元素添加到队尾  

 持续向上移动并交换 

 

如上图所示: 

class BinaryHeap:
    def __init__(self):
        '''初始化数组'''
        self.data = [None]

    def get_parent_index(self, index):
        '''
        父节点索引
        :param index:
        :return:
        '''
        # 判断数组是否越界
        if index == 0 or len(self.data) - 1 < index:
            return None
        # 返回父节点  等价于 (index -1)>>1
        return (index -1) // 2

    def insert(self, data):
        """
        1. 先把元素放到最后, 然后从后往前依次堆化
        2. 大堆顶为例, 如果插入元素比父节点大, 则交换, 直到最后
        :param data:  插入元素
        :return: 返回数组
        """
        self.data.append(data)
        index = len(self.data) - 1  # 插入元素的下标
        parent = self.get_parent_index(index)
        # 判断父节点不为空,且父节点元素<子节点元素,循环
        while parent is not None and self.data[parent] < self.data[index]:
            # 交换
            self.data[parent], self.data[index] = self.data[index], self.data[parent]
            #元素下标为之前父节点,继续初始化值
            index = parent
            parent = self.get_parent_index(parent)
        return self.data


# 使用示例

if __name__ == '__main__':
    #二叉堆对象
    heap = BinaryHeap()
    ll=[100,90,80,70,60,20,33,15,50]
    print(ll)
    #数组
    heap.data=ll
    #添加数据
    print(heap.insert(95))

 

2、删除节点

1、将堆尾元素替换到顶部(即对顶被替代删除掉)

2、依次从根部向下调整整个堆的结构(一直到堆尾即可) 

删除元素100

​​​​​​​

如上图所示: 

class BinaryHeap:
    def __init__(self):
        '''初始化数组'''
        self.data = [None]

    def removeMax(self):
        # 保存删除的元素
        remove_data = self.data[0]
        # 首尾互换参数
        self.data[0] = self.data[-1]
        #删除最后一个
        del self.data[-1]

        # 堆化
        self.heapify(0)
  
        return self.data

    def heapify(self, index):
        # 从上往下堆化,从index 开始堆化操作 (大顶堆)
        total_index = len(self.data) - 1
        while True:
            maxvalue_index = index
            # 左右子节点索引
            left = 2 * index + 1
            right = 2 * index + 2
            #查找根,左,右中最大值
            if left <= total_index and self.data[left] > self.data[maxvalue_index]:
                maxvalue_index = left
            if right <= total_index and self.data[right] > self.data[maxvalue_index]:
                maxvalue_index = right
            if maxvalue_index == index:
                break
            self.data[index], self.data[maxvalue_index] = self.data[maxvalue_index], self.data[index]
            index = maxvalue_index



if __name__ == '__main__':
    #二叉堆对象
    heap = BinaryHeap()
    ll=[100,90,80,70,60,20,33,15,50,40]
    print(ll)
    #数组
    heap.data=ll
    #删除最大元素
    print(heap.removeMax())

 

 

 由此得出:Binaey Heap 的 find Min/Max 的时间复杂度为 o(1),其余时间复杂度为 o(logn)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值