堆(Heap)的相关知识学习
1、堆的概念
- 堆逻辑上是一棵完全二叉树
- 堆物理上是保存在数组中
- 满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆
- 反之,则是小堆,或者小根堆,或者最小堆
2、堆的操作
(1)向下调整
过程(以小堆为例):
- index 如果已经是叶子结点,则整个调整过程结束
- 判断 index 位置有没有孩子
- 因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子
- 因为堆的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,即 left >= size 越界
- 确定 left 或 right,谁是 index 的最小孩子 min
- 如果右孩子不存在,则 min = left
- 否则,比较 array[left] 和 array[right] 值得大小,选择小的为 min
- 比较 array[index] 的值 和 array[min] 的值,如果 array[index] <= array[min],则满足堆的性质,调整结束
- 否则,交换 array[index] 和 array[min] 的值
- 然后因为 min 位置的堆的性质可能被破坏,所以把 min 视作 index,向下重复以上过程
代码实现:
public static void adjustDown(int[] array, int size, int index) {
while (true) {
// 1. 判断 index 是不是叶子
int leftIndex = 2 * index + 1;
if (leftIndex >= size) {
return;
}
// 2. 找最小的孩子
int minIndex = leftIndex;
int rightIndex = leftIndex + 1;
if (rightIndex < size && array[rightIndex] < array[leftIndex]) {
minIndex = rightIndex;
}
// 3. 比较最小孩子的值 和 index 位置的值
if (array[index] <= array[minIndex])