数据结构:二叉完全树(堆)

参考文章

堆常用来实现优先队列。
用数组保存数据,而不是链表。

在队列中,操作系统调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种(完全二叉树
完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树

大根堆和小根堆

最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子(如果存在)的键值的树。大顶堆是一棵完全二叉树,同时也是一棵最大树。小顶堆是一棵完全完全二叉树,同时也是一棵最小树。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

  • 堆中任一子树亦是堆。
  • 以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。

如下图所示,图一为最大堆,图二为最小堆:
image.png

基本操作

  • 上浮 shift_up;
  • 下沉 shift_down
  • 插入 push
  • 弹出 pop
  • 取顶 top
  • 堆排序 heap_sort

以小根堆为例:
堆可以用数组存储数据,如有数组:{8,5,2,9,3,7,1,4,6}
则可以构成堆:
image.png

可以发现:任意节点的左右孩子对应数组下标的一半为其父节点对应的下标(5/24/22)。
注意:这里下标从1开始计算而不是从0开始,因为从0开始的话根节点的下标和子节点下标间就没有了倍数关系(5/2 != 6/2)

上浮

从当前结点开始,和它的父亲节点比较,若是比父亲节点来的小,就交换,然后将当前询问的节点下标更新为原父亲节点下标;否则退出。
image.png

下沉

经过上浮操作之后,下标3处节点的元素值如下图所示
image.png

让当前结点的左右儿子(如果有的话)作比较,哪个比较小就和它交换,并更新询问节点的下标为被交换的儿子节点下标,否则退出。

插入

每次插入的时候呢,都往最后一个插入,然后使它上浮。

弹出(删除根节点元素)

让根节点元素和尾节点进行交换,然后让现在的根元素下沉就可以了。

取顶

根节点数组下标必定是 0,返回堆数组中下标为 0 的元素即可。

堆排序

见算法 - 排序系列文章第六篇,同时用代码实现上述对堆的操作。

发布了110 篇原创文章 · 获赞 50 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/aimeimeiTS/article/details/84999558