堆,建堆,堆排序,堆删除和堆插入


注意:看这篇文章之前,你一定要知道完全二叉树的结构

首先要明白一点,堆是一种数据结构,和队列,链表,树等等一个级别。

堆的定义

堆是一棵节点含有内部比较器的完全二叉树。(说白了,堆就是完全二叉树,只不过它的节点对象实现了comparable接口)。

也有种说法是,一个可以自我调整的完全二叉树


堆的特性

  • 每个父节点都大于等于(或者小于等于)其所有后代结点。
  • 堆的根节点含有堆中最大(或者最小)的对象。
  • 堆中以任意节点为根节点的子树仍然是堆。

堆的分类

最大堆(大根堆,大顶堆):根节点对象是最大对象的堆

最小堆(小根堆,小顶堆):根节点对象是最小对象的堆


接下来就是堆的应用了,这里我只用最大堆举例,最小堆和最大堆差不多,会一个另一个就懂了

第一个:建堆(将数组变为堆)

建堆的思想用的是自底向上的思想

①我们现在有一个长度为n的数组a,里边的元素都没有顺序,但是每个元素都实现了内部比较器。

②然后我们新建一个完全二叉树b,按数组下标0到n-1的顺序依次放入完全二叉树,也就是说现在b[0]=a[0],b[1]=a[1]......。

③下一步我们需要找到最后一个非终端节点(最简单的找法就是从最后一个节点b[n-1],然后b[n-2]....依次往前找,直到找到一个节点,它有左节点,或者左右节点都有,这个节点就是最后一个非终端节点,也叫最后一个父节点)。

④找到了这个父节点之后,我们来看他的左右节点,我们把左右节点进行比较,找出最大的那个节点,然后将这个最大节点(左或右节点)和父节点进行比较,如果最大节点大于父节点,那就交换,不然就跳过

⑤从最后一个父节点,到倒数第二个父节点,再依次往上,直到根节点(也就是第一个父节点),对每一个父节点都执行第④步的比较操作。

⑥注意!注意!注意!这一步和第五步是同步发生,它不是最后一步,也就是说一旦第五步发生了交换操作(左右节点中的一个和父节点交换了),这一步就要开始执行,这一步的名字叫做递归调整,当发生了交换操作时,我们把交换操作中的子节点(左或右节点)作为根节点c[0],然后找出这个根节点所代表的子树c,从第一个父节点c[0](也就是根节点),第二个父节点c[1],再依次往下,直到最后一个父节点,对每一个父节点都执行第④步的比较操作。

至此,我们就得到了初始堆。

下面是例子1:



例子2:https://blog.csdn.net/u011240016/article/details/53428489


第二个:堆排序(利用堆的性质所设计的一种排序算法)

如果说第一个建堆你完全理解了,那么这个堆排序你就没问题了。

推排序的基本思想

在建堆的基础上,把堆首元素和堆尾元素互换,然后堆容量减一,接着为了维持堆的性质,需要对容量减一的堆(其实这时候因为元素顺序被打乱,已经不能叫堆了,可以叫二叉树)重新进行建堆,重复以上步骤,直到堆的容量只剩下1,这时就已经得到了排序完成的二叉树。

你是不是想问堆的性质是啥?上边已经说过了,堆的根节点含有堆中最大(或者最小)的对象。

堆排序其实也就是给堆的排序,排完序的堆就不叫堆了,本质上也就是个有序数组。

更详细的例子和讲解可以看这个博客:https://blog.csdn.net/sun_ru/article/details/52004044

第三个  插入,删除

插入的基本思想很简单,你在堆的最后新加一个节点,再对这个新构成的二叉树数组(新增了一个元素的堆)进行建堆即可。

删除也很简单,对于堆来讲删除就只能删除根节点,在堆里,你不能直接删除,你需要把堆尾元素剪切,复制到堆首,覆盖掉原来的堆首元素,然后还是再对这个新构成的二叉树数组(删掉一个元素的堆)进行建堆即可。

更详细的例子和讲解可以看这个博客:https://blog.csdn.net/hrn1216/article/details/51465270


  • 26
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值