最大堆的实现 根节点从零开始编号
import java.util.ArrayList;
import java.util.List;
public class Maxheap {
//保存元素的数组使用JDK动态数组
private List<Integer> arr;
//当前最大堆有效元素的个数
private int size;
public Maxheap() {
this(10);
}
public Maxheap(int capacity) {
this.arr = new ArrayList<>(capacity);
}
//接收任意数组调整成最大堆
public Maxheap(int[] nums) {
this.arr = new ArrayList<>(nums.length);
for (int i : nums) {
arr.add(i);
size++;
}
//将最后一个非子叶节点不断向上调整为最大堆
for (int i = father(size - 1); i >= 0; i--) {
siftdown(i);
}
}
public int peekMax() {
if (isEmpty()) {
throw new IllegalArgumentException("heap is empty!cannot peek!");
}
return arr.get(0);
}
//从下标k开始进行元素的下沉操作
private void siftdown(int k) {
//当前在子树
while (leftChild(k) < size) {
int j = leftChild(k);
if (j + 1 < size && arr.get(j) < arr.get(j + 1)) {
j = j + 1;
}
// 此时j一定对应了左右子树的最大值索引
if (arr.get(k) >= arr.get(j)) {
// 当前元素对应的k已经落到了最终位置
break;
} else {
//当前元素k小于子树的最大值,将子树最大值交换上去
seap(k, j);
//继续向上判断
k = j;
}
}
}
// 获取当前节点的父节点编号
private int father(int k) {
return (k - 1) >> 1;
}
// 获取当前节点的左子树节点编号
private int leftChild(int k) {
return (k << 1) + 1;
}
// 获取当前节点的右子树节点编号
private int rightChild(int k) {
return (k << 1) + 2;
}
public boolean isEmpty() {
return size == 0;
}
@Override
public String toString() {
return arr.toString();
}
public void add(int val) {
//默认尾插
this.arr.add(val);
size++;
//进行元素上浮
//此时size-1是最后一个有效元素
siftup(size - 1);
}
// 移除当前最大堆的最大值并返回
public int extractMax() {
if (isEmpty()) {
throw new IllegalArgumentException("heap is empty!cannot extract!");
}
int maxVal = arr.get(0);
// 1.将当前最后一个元素覆盖到堆顶
// arr[0] = arr[size - 1]
arr.set(0, arr.get(size - 1));
// 2.删除当前数组中的最后一个元素
arr.remove(size - 1);
size--;
// 3.从根节点开始进行元素的下沉操作
siftdown(0);
return maxVal;
}
// 元素上浮操作,将索引为k的元素上浮使得当前完全二叉树仍然满足堆的性质
private void siftup(int k) {
//终止条件
//1.k == 0没有父节点,当前元素已经到达最终位置
// 2.arr[k] <= arr[parent[k]],当前元素已经到达最终位置
// 继续条件 : 还存在父节点,且当前元素 > 父节点
while (k > 0 && arr.get(k) > arr.get(father(k))) {
seap(k, father(k));
//继续向上判断
k = father(k);
}
}
private void seap(int i, int j) {
int temp = arr.get(i);
arr.set(i, arr.get(j));
arr.set(j, temp);
}
}