目录
一、堆
整体结构思维导图
-------------------------------------------------------------------------------- 回到目录
堆的相关知识:
- 堆是一棵完全二叉树;
- 堆要满足的性质是每一个结点都大于孩子,或者都小于孩子结点的值;
最大堆: 所有结点都比自己的孩子结点大;
最小堆: 所有结点都比自己的孩子结点小;
数组里的索引公式:
我们用数组来表示堆,位置从0开始(也可以从1开始,只是公式有点小变动)。右下角的三个索引公式可以用肉眼验算。
建堆过程:
我们从最后一个非叶子结点(22)开始建堆,然后依次往前一个节点建堆,在建堆过程中,若位置交换完之后还能继续往下交换,就继续交换直至不能交换为止。
该节点的索引为((arr.length - 1) - 1) / 2
建最大堆的完整图示(顺序从左到右):
使用动态数组实现堆
注意:
- add()是先把元素加入到动态数组的最后,然后向上浮,注意其中的 siftUp 操作就是将一个元素向上浮使其满足最大堆的操作。
- extractMax()就是取出堆顶的元素并且返回,步骤是先交换堆顶和最后一个元素,然后将新的堆顶往下沉。
- 从 (arr.length - 1 - 1) / 2开始建堆。
- 取出操作只能取最大的元素。
- siftDown() 先把最后一个元素顶到第一位,使树结构保持不变,然后再从左右孩子中找最大的反复交换位置让其重新满足最大堆性质。
//若是使用的自己实现的数组,在Array基础上再加两个函数
public void swap(int i, int j) {
if (i < 0 || i >= size || j < 0 || j >= size)
throw new IllegalArgumentException("illegal");
E t = data[i];
data[i] = data[j];
data[j] = t;
}
public Array(E[] arr) {
data = (E[])new Object[arr.length];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
}
size = arr.length;