数据结构之堆(Heap),堆的相关操作,用堆模拟优先级队列

目录堆的概念堆的存储方式堆的相关操作堆的向下调整。堆的创建堆的插入和向上调整堆的删除用堆模拟优先级队列堆的概念堆是逻辑结构为二叉树存储结构为数组数组的一种数据结构,为什么这么说呢?因为我们就是把堆想象成一棵有特殊功能的二叉树,然后把它按照层序遍历的顺序放到数组中。堆有大堆小堆之分,大堆是指根节点为堆中最大值的堆,小堆是指根节点为堆中最小值的堆。堆中某个节点的值总是小于等于或大于等于其父亲节点的值,前者称为就是大堆,后者为小堆。堆总是一棵完全二叉树。小堆:大堆:可以看到小堆的父亲节点都小于
摘要由CSDN通过智能技术生成

堆的概念

堆是逻辑结构为二叉树存储结构为数组数组的一种数据结构,为什么这么说呢?因为我们就是把堆想象成一棵有特殊功能的二叉树,然后把它按照层序遍历的顺序放到数组中。堆有大堆小堆之分,大堆是指根节点为堆中最大值的堆,小堆是指根节点为堆中最小值的堆。

  • 堆中某个节点的值总是小于等于或大于等于其父亲节点的值,前者称为就是大堆,后者为小堆。
  • 堆总是一棵完全二叉树。

小堆:在这里插入图片描述

大堆:
在这里插入图片描述
可以看到小堆的父亲节点都小于孩子节点,进而也就有了小堆根节点是全堆中最小的值。
同样的大堆的父亲节点都大于孩子节点,进而有了大堆的根节点是全堆中最大的值。

堆的存储方式

因为我们要把堆按照层寻遍历的顺序存在数组中,那么在数组这么一个线性结构中怎么找一个节点的孩子节点,怎么找到一个节点的父亲节点呢?
答案是——根据下标。我们先在一棵二叉树中找以下节点之间的规律:
在这里插入图片描述
我们把上面这棵树按照层序遍历顺序存在数组中的下标标记了,我把节点的规律告诉大家,大家可以根据对照理解:

设一个节点的下标为 X, 那么它的左孩子下标为 2X + 1,右孩子下标为2X + 2,父亲节点为 (X - 1) / 2 。

这里解释一下,不用疑惑计算父亲节点的当前节点是它父亲节点左孩子还是右孩子,如果是左孩子的话根据上面左孩子计算父亲节点的公式 2X + 1可以知道左孩子坐标减一除以二刚好是父亲节点下标,如果是右孩子的话减一除二会自动向下取整,算出的下标也刚好是父亲节点的下标。

堆的相关操作

堆的向下调整。

对于集合{27, 15, 19, 18, 28, 34, 65, 49, 25, 37}中的数据,将它建造成堆是这样的:
在这里插入图片描述
可以发现这个堆除了根节点以外都满足小堆的性质,那么这种情况我们应该怎么处理?关于堆的第一个操作——向下调整。

 //index为需要调整的节点下标
    public static void heapifySmallHeap(long[] array, int size, int index){
   
        while (true){
   
            //需要调整节点的左孩子下标
            int leftIndex = index * 2 + 1;
            //如果不存在左孩子那么
            // 因为堆是完全二叉树就一定不存在右孩子
            //如果左孩子下标大于等于堆的总结节点数
            // 就return
            if (leftIndex >= size){
   
                return;
            }
            //存在左孩子,现在看右孩子
            int rightIndex = leftIndex + 1;
            //先令左右孩子中值小的节点下标等于
            //minIndex,让该值等于smallVal
            int minIndex = leftIndex;
            long smallVal = array[minIndex];
            //先判断右孩子是否存在
            if (rightIndex < size){
   
                //右孩子存在的话让右孩子的值和smallVal的值比较
                // 从而让small存左右孩子中最小的值
                // 让minIndex为最小值节点下标
                if (array[rightIndex] < smallVal){
   
                    minIndex = rightIndex;
                    smallVal = array[rightIndex];
                }
            }
            //判断要调整父亲节点和smallVal的大小
            if (array[index] <= smallVal){
   
                return;
            }
            //交换父亲节点和smallVal节点
            array[minIndex] = array[index];
            array[index] = smallVal;
            index = minIndex;
        }
    }

按照向下调整代码调整一下例子中的堆:
在这里插入图片描述
最终在d中堆被调整完成。
这里需要注意的是:在调整以index为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整。
时间复杂度分析:最坏的情况即上图的情况࿰

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有裂痕的石头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值