1. 堆的概念
把元素集合 k = {k0, k1, k2, …, kn-1} 按完全二叉树的顺序存储在一个一维数组中,并满足:
ki <= k2i + 1 且 ki <= k2i + 2(ki >= k2i + 1 且 ki >= k2i + 2)i = 0, 1, 2, 3…,则称为小堆(或大堆)。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
- 堆中某个节点的值总是不大于或者不小于其父节点的值;
- 堆总是一颗完全二叉树。
大根堆
小根堆
2. 堆的创建
2.1 堆向下调整
前提:除了要调整的位置之外,其余的数据以满足堆的性质。
public static void shiftDown(long[] array, int size, int index){
while (true){
int leftIndex = 2 * index + 1;
if (leftIndex >= size){
return;
}
int rightIndex = leftIndex + 1;
int minIndex = leftIndex;
if (rightIndex < size && array[rightIndex] < array[leftIndex]){
minIndex = rightIndex;
}
if (array[index] <= array[minIndex]){
return;
}
long t = array[index];
array[index] = array[minIndex];
array[minIndex] = t;
index = minIndex;
}
}
2.2 堆的创建
public static void creatHeap(long[] array, int size){
// 找到第一个非叶子节点,从该节点位置开始往前一直到根节点,遇到一个节点,应用向下调整
for (int i = (size - 2) / 2; i >= 0; i--){
shiftDown(array, size, i);
}
}
2.3 堆的插入
- 将元素放入到底层空间;
- 将最后新插入的结点向上调整,知道满足堆的性质。
public static void shiftUp(long[] array, int index){
while (index > 0){
int parent = (index - 1) / 2;
if (array[parent] < array[index]){
return;
}else {
// 将双亲与孩子节点进行交换
long t = array[index];
array[index] = array[parent];
array[parent] = t;
index = parent;
parent = (parent - 1) / 2;
}
}
}
2.4 堆的删除
- 将堆顶元素和堆中最后一个元素交换
- 将堆中有效数据个数减少一个
- 对堆顶元素进行向下调整。
3. 堆的应用
- 用堆作为底层结构封装优先级队列
- 堆排序