堆是一颗完全二叉树。
简而言之,一个二叉树是饱满的---即二叉树都满了,即使没有饱满,那么上一层都是饱满,最后一层叶子节点从左向右排列。
但是堆相对于完全二叉树有了自己的特点,堆分成最大堆及最小堆,
对于最大堆有:
1、根节点(堆顶)的关键字是最大(至少要大于或等于)的;
2、父亲节点必然比左右子节点都要大(至少等于)--左右节点之间没有大小之分,但是都比父亲节点少。
对于最小堆,性质类似:
1、根节点(堆顶)比所有子节点都小或等于;
2、父亲节点比左右子节点都要小或等于。
堆的存储
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
堆操作
最大堆的插入 --- 节点上浮
由于需要维持完全二叉树的形态,需要先将要插入的结点x放在最底层的最右边,插入后满 足完全二叉树的特点;然后把x依次向上调整到合适位置满足堆的性质,例如下图中插入80,先将80放在最后,然后两次上浮到合适位置.
时间:O(logn)。 “结点上浮”
最大堆的删除 --- 节点下沉
操作原理是:当删除节点的数值时,原来的位置就会出现一个孔,填充这个孔的方法就是,把最后的叶子的值赋给该孔并下调到合适位置,最后把该叶子删除。 节点下沉
堆的初始化
调整法:
序列对应一个完全二叉树;从最后一个分支结点(n div 2)开始,到根(1)为止,依次对每个分支结点进行调整(下沉),
以便形成以每个分支结点为根的堆,当最后对树根结点进行调整后,整个树就变成了一个堆。
时间:O(n)
对如图的序列,要使其成为堆,我们从最后一个分支结点(10/2),其值为72开始,依次对每个分支节点53,18,36 45进行调整(下沉).
参照:
https://blog.csdn.net/morewindows/article/details/6709644/
https://blog.csdn.net/abcd1f2/article/details/47260095