堆的性质
①堆在物理上用数组存储, 逻辑上是二叉树的形式
②小堆: 任意节点的值都不小于父节点的值
大堆: 任意节点的值都不大于父节点的值
堆的向下调整
以小堆为例
向下调整的前提:
①除了要调整的位置外, 其他位置都满足堆的性质
// 3, 向下调整
public void downHeap(int[] arr, int size, int index) {
// 没有此位置的元素
if (index < 0 || index >= size) {
return;
}
while (true) {
int left = index * 2 + 1;
// 无孩子, 无需调整
if (left >= size) {
return;
}
int small = left;
int right = left + 1;
if (right < size && arr[right] < arr[left]) {
small = right;
}
if (arr[small] >= arr[index]) {
return;
}
swap(arr, small, index);
index = small;
}
}
堆的向上调整
// 2. 向上调整
public void upHeap(int[] arr, int size, int index) {
// 没有此位置的元素
if (index < 0 || index >= size) {
return;
}
while (true) {
if (index <= 0) {
return;
}
int parent = (index - 1) / 2;
if (arr[parent] > arr[index]) {
swap(arr, parent, index);
} else {
// 无需调整
}
index = parent;
}
}
堆的建立
// 1. 建小堆
public int[] buildHeap(int[] arr, int size) {
// 找到最后一个结点的父节点
int index = (size - 1) / 2;
for (int i = index; i >= 0; i--) {
downHeap(arr, size, i);
}
return arr;
}
堆的插入
// 插入
public void insert(int[] arr, int size, int val) {
arr[size] = val;
upHeap(arr, size + 1, size);
}
堆的删除
// 删除
public void remove(int[] arr, int size) {
swap(arr, 0, size - 1);
downHeap(arr, size - 1, 0);
}
private void swap(int[] arr, int parent, int index) {
int temp = arr[parent];
arr[parent] = arr[index];
arr[index] = temp;
}