前言
什么是二叉堆?
看下百度百科的定义:
二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
完全二元树,我们是知道的。
近似完全二元书,是啥意思呢?就是下面这个E可能没有。
所以叫近似。
有几个术语值得注意,因为计算机的人读多了专门喜欢讲官话,不像我业务开发人员这么土气。
二叉堆的根节点叫做堆顶。
这个堆顶呢,在最大堆中叫最大元素,在最小堆中叫最小元素。
正文
二叉堆,一听这种结构稳定的东西,花样就多。
看下二叉堆是如何进行排序的,假如是最小堆,也就是要栈顶要最小,父结点的键值总是小于或等于任何一个子节点的键值。
无论如何我们知道这个排序肯定是一个上浮的过程,为什么可以这么说呢?要确定的元素是栈顶,栈顶是一个稳定的存在,也就是说比较的无论是最大堆或者最小堆,要不一开始栈顶就是最大或者最小,要不肯定是子节点浮上去的。
假设如图:
要让1浮到最顶层,这样是不符合计算机思维的,计算机思维在于重复确认正确信息。
如前面所说,一定是从下一个浮起的。那么可以从最后一个元素开始判断。
像这种稳定且饱满的结构,一般要用稳定的结构存取,比如说数组。
数组如下:
0 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
10 | 7 | 2 | 8 | 6 | 1 | 5 | 3 | 9 |
数组与下标对应对上。
最后一个数字为9,那么找到他的父元素位置,通过(left-2)/2,得到8,同样得到8的右子节点为3,那么寻找最小值替换8,也就是3替换8,小的网上浮。
图如下:
结果如下:
0 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
10 | 7 | 2 | 3 | 6 | 1 | 5 | 8 | 9 |
然后修改后3的位置,也就是原来8的位置,找到父节点,通过(right-1)/2,得到为7.
那么7 3 6开始比较,3的位置开始上浮。
同理,然后3 10 2开始对比,2最小,然后2上浮,10往2的位置下浮。
如下:
然后找到当前10的位置,也就是原先2的位置,然后2 1 5,判断1上浮。
因为1原来的位置,是右叶子节点,如何判断是否是叶子节点?因为可以计算出其右叶子节点的位置,如果该位置大于数据的最后一个位置,那么一定是叶子节点,所以继续1现在的位置,也就是3 2 1开始比较。
然后1和2位置替换,然后结束。
二叉堆的作用
二叉堆有什么用呢?涉及到到一个优先队列的问题。
比如最大堆,加上是优先最大值出去。我们发现一个问题,我们的需求是最大值,而不是全部排序,这个问题就很有意思了。
二叉堆序列化,最大堆的栈顶做delete,然后部分调整即可。