zoukankan      html  css  js  c++  java
  • 二叉堆的插入,删除和构建

    二叉堆的本质是一个完全二叉树,它分为最大堆,和最小堆(所以学好二叉堆就要学好二叉树的知识点,感觉这些数据结构都是依次递进,有点进化的味道)

    二叉堆的插入

    插入节点:

    也叫上浮

    上浮就是孩子节点不断与父节点之间进行比较

    最小堆的化,

    孩子节点比父节点小,上浮;

    最大堆的化,

    孩子节点比父节点大,上浮;
    其他情况那就不动;当然堆的插入肯定是已经构建好的堆

    插入的位置:

    就是插入位置是完全二叉树的最后一个位置,也就是最新的一个叶子节点(叶子节点插入从左到右))

    def up_adjust(array=[]):
        child_index = len(array) - 1 # 左孩子节点
        parent_index = (child_index - 1) // 2 # 父节点
        # temp保存插入的叶子节点值,用于最后的赋值
        temp = array[child_index]
        i = 0
        while child_index > 0 and temp < array[parent_index]: #孩子节点索引大于0和孩子节点的值小于父节点的值
            # 无需真正交换,单向赋值即可
            array[child_index] = array[parent_index]
            child_index = parent_index
            parent_index = (parent_index - 1) // 2 # 在继续寻找父节点的父节点
            i += 1 # while就可以用,函数就不能
        array[child_index] = temp #把原来孩子节点的值赋值给孩子节点上浮索引的位置 
        print('上浮了多少%d次'%i)
    

    代码优化的点:

    这里的无需真正交换,单向赋值意思是:这里实际变化的是孩子节点的值,而最终退出循环的那个孩子节点的值又被最开始插入的值赋值。并没改变相对于那个孩子节点父节点的值。这样其实降低了时间复杂度和空间复杂度。

    二叉堆的下沉

    二叉堆的节点下沉操作;
    下沉是父节点与左右孩子节点中较小的那个互换;可先假定左孩子小设定左孩子索引为child_index,
    在再假设中假设右孩子比左孩子小,成立的话就执行child_index+1操作.不成立则没有操作
    接着判断父节点小于任何一个孩子的值,直接跳出
    接着进行父节点与最小的孩子节点之间的互换
    这里要做的删除要删除的节点,然后把最后一个节点的数据放在该删除的节点位置,然后进行下沉操作
    所以这里仅仅是下沉,并没有删除节点的操作

    def down_adjust(parent_index, length, array=[]):
       
        # temp保存父节点值,用于最后的赋值
        temp = array[parent_index]
        child_index = 2 * parent_index + 1
        i = 1
        while child_index < length: # 循环条件是孩子节点索引小于数组长度
            # 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            # 没有的话,下面这条if语句就不执行
            if child_index + 1 < length and array[child_index + 1] < array[child_index]:
                child_index += 1
            # 如果父节点小于任何一个孩子的值,直接跳出
            if temp <= array[child_index]:
                break
            # 无需真正交换,单向赋值即可
            array[parent_index] = array[child_index] # 父节点的值变为孩子节点的值,这里并没有改变孩子节点的值
            parent_index = child_index # 父节点的索引变为孩子节点,这一步才是最重要的,但他省略了孩子节点的值变为父节点的值
            child_index = 2 * child_index + 1 # 孩子节点再找出孩子节点
            i+=1
        array[parent_index] = temp #把父节点赋值给最后定位到的孩子节点 
        print('下沉了多少%d次'%i)
    
    

    二叉堆的删除

    二叉堆的删除是建立再二叉堆的下称之上的,只是下沉的父节点变为了那个最后一个叶子节点

    删除操作的进行:

    这里要做的是把要删除的节点删除,然后把最后一个节点的数据放在该删除的节点位置,然后进行下沉操作
    下沉操作的临时变量temp也是该值,然后下沉

    def down_adjust1(parent_index, length, array=[]):
        temp = array[length-1]
        # 这里要删除最后一个元素,并把最后一个元素的值赋值给要堆顶
        array[parent_index]=array[length-1]
        array.pop()
        child_index = 2 * parent_index + 1
        i = 1
        while child_index < length: # 循环条件是孩子节点索引小于数组长度
            # 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            # 没有的话,下面这条if语句就不执行
            if child_index + 1 < length and array[child_index + 1] < array[child_index]:
                child_index += 1
            # 如果父节点小于任何一个孩子的值,直接跳出
            if temp <= array[child_index]:
                break
            # 无需真正交换,单向赋值即可;孩子节点索引变为父节点,父节点的值自然变了
            array[parent_index] = array[child_index] # 父节点的值变为孩子节点的值,这里并没有改变孩子节点的值
            parent_index = child_index # 父节点的索引变为孩子节点,这一步才是最重要的,但他省略了孩子节点的值变为父节点的值
            child_index = 2 * child_index + 1 # 孩子节点再找出孩子节点
            i+=1
        array[parent_index] = temp #把父节点赋值给最后定位到的孩子节点 
        print('下沉了多少%d次'%i)
    

    二叉堆的构建

    构建二叉堆就是把一个无序的完全二叉树调整为二叉堆,本质就是让所有非叶子节点依次下称
    首先找到最后一个非叶子节点len(array)-2) // 2,然后按照顺序把其他非叶子节点依次下沉

    def build_heap(array=[]):
        """
        二叉堆的构建操作
        :param array: 原数组
        """
        # 从最后一个非叶子节点开始,依次下沉调整
        for i in range((len(array)-2) // 2, -1, -1):
            down_adjust(i, len(array), array) # 这里调用下沉操作
    

    二叉堆索引的技巧

    二叉堆虽然是完全二叉树,但它的存储方式并不是链式存储,而是顺序存储,也就是二叉堆的所有节点都存储在数组中
    这里假设父节点的下标是p,那么它左孩子节点就是2p+1.右孩子节点就是2p+2(节点均指索引)
    同理假设左孩子节点是c,那么它的父节点是(c-1)//2

    还有获取一个列表中所有父节点的索引

    len(array)-2) // 2

    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    Python语言基础04-构造程序逻辑
    Python语言基础03-分支和循环结构
    Python语言基础02-变量和运算
    Python语言基础01-初识Python
    Hadoop+Hbase分布式集群架构“完全篇”
    kubernetes系列12—二个特色的存储卷configmap和secret
    安装AIDE文件完整性检测
    PAM和账户安全配置
    SSH安全配置
    CentOS7的审计配置
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15339229.html
Copyright © 2011-2022 走看看