二叉堆的添加及删除元素方法实现

本次以最大堆来讨论二叉堆的添加以及删除元素的方法,对于最大堆,一定满足两个条件:

  1. 二叉堆中的父节点的值一定大于其子节点的值。

  2.二叉堆一定为一颗满二叉树。

根据上面对于二叉堆的特点,我们可以很简单的找到给二叉堆添加元素的方法,首先二叉堆实际上是以数组来存储的,并且父节点的索引与子节点的索引都相互存在着一定的关系,因此对二叉堆的操作实际上就是对数组的操作。


首先我们来考虑给二叉堆添加元素的方法实现:

给二叉堆添加元素时,在数组的后一个元素加入其值,然后判断该元素是否在正确的位置上,即是否满足其值要小于其父节点的值,不满足的话则需要调换其位置。

例如如下图中,我们在数组11号中添加了一个值为52的元素,但其值要比其父节点还大,因此就破坏了二叉堆的特性,此时,我们只需要把插入的节点和其父节点调换一下位置即可。我们把向上与父节点调换位置的操作称为shiftup。



然后接下来只要一直进行shift的循环操作,使其添加的节点能找到属于自己正确的位置,则停止与父节点的调换。





以下为shift代码的具体实现:

void shiftup(int index)//index为添加的新元素在数组中的索引
    {
        while(index>1&&data[index]>data[index/2])//防止数组越界操作以及判断新节点是否大于其父节点
        {
            swap(data[index],data[index/2]);//如果大于则不满足二叉堆的条件,交换之
            index/=2;//index更新其为父节点所在的索引(因为与父节点的值进行了调换)
        }
    }


我们接下来向二叉堆中插入5个随机值,然后看这5个值是否按照我们的预期正确的排列成了一个最大二叉堆。



我们可以在图纸上画出一颗二叉堆来,发现其完全满足条件。


接下来我们来考虑一下二叉堆的删除方法:

对于二叉堆来说,每次删除都是删除堆顶的元素,最大或者最小的元素,本次我们以最大堆来讨论:

对于最大堆来说,删除堆顶的元素,则堆顶的元素空缺的位置由整个堆的最后一个元素放到堆顶即可,这样还可以满足二叉树的完全性,然后把count减一个单位(count指向最后一个元素),此时数组就不会访问到最后一个被移到堆顶的元素了。

接下来我们在看如何调整被移到堆顶的元素的位置,假设我们称被移到堆顶的元素为替代位,则我们看替代位是否满足二叉堆的条件,即其值必须要大于它的根节点的值,如果不满足则需要向下与真正满足当父节点的节点进行替换,如果该替换位下面有两个子节点,则应该取二者之间的最大者与替换位进行替换,只有这样替换后才能满足父节点大于两个子节点的要求。对于像这样向下移动位置我们称其为shiftdown操作。

例如下图中替代位的值为52,根本不满足二叉堆的特性,因此我们将其与较大的子节点30进行替换。






以下为代码的具体实现:


 item extractmax()//删除堆顶元素的操作
    {
        item ret=data[1];
        swap(data[1],data[Count]);//把最后一个元素替换到堆顶
        Count--;//更新数组的界限
        shiftdown(1);//对堆顶元素进行shiftdown操作
        return ret;
    }


void shiftdown(int n)
    {
        while(2*n<=Count)//保证n不是叶子节点,叶子节点无子节点,防止越界访问
        {
            int j=2*n;//j指向子节点中的大者,默认为左孩子
            if(j+1<=Count&&data[j+1]>data[j])//如果存在右孩子并且右孩子比左孩子还大
                {
                    j++;//j就指向右孩子
                }
                if(data[n]>data[j]) break;//父节点比子节点中的大者还要大,满足二叉堆的条件
                else
                {
                    swap(data[n],data[j]);//不满足条件则向下交换位置
                }
                n=j;//更新索引
        }
    }



我们接下来看一下二叉堆是否正确的进行了删除操作:


此时,二叉堆的堆顶最大的元素97已经被删除,并且剩下的4个元素仍然满足二叉堆的条件.


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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论 3

打赏作者

刘扬俊

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值