二叉堆实现
import java.util.Arrays;
//二叉堆
public class BinaryHeap {
private static final int DEFAULT_CAPACITY = 10;
private int currentSize;
private int[] arr;
public BinaryHeap() {
this(DEFAULT_CAPACITY);
}
public BinaryHeap(int defaultCapacity) {
currentSize = 0;
arr = new int[defaultCapacity];
}
public BinaryHeap insert(int x) {
if (currentSize == arr.length - 1) {
throw new RuntimeException("溢出...");
}
// 首先假设,将待插节点放在叶子节点的末端处
int pos = ++currentSize;
// 如果根节点还没有下滤过,并且待插节点小于pos的父节点
while (pos > 1 && x < arr[pos / 2]) {
// 父节点下滤
arr[pos] = arr[pos / 2];
// pos上移
pos /= 2;
}
arr[pos] = x;
return this;
}
public int delete() {
if (currentSize == 0) {
throw new RuntimeException("堆空...");
}
int min = arr[1];
int temp = arr[currentSize--];
int pos = 1;
int child = pos * 2;
// 当pos位置还不是叶子节点时
while (pos * 2 <= currentSize) {
// 找到pos的孩子节点
child = pos * 2;
// 当pos不是只有左孩子,并且右孩子小于左孩子
if (child != currentSize && arr[child + 1] < arr[child]) {
child++;
}
// 如果最小的孩子小于temp
if (arr[child] < temp) {
// 孩子节点上滤
arr[pos] = arr[child];
} else {
// pos的最小孩子比temp大,此时应跳出循环,将temp赋给pos位置
break;
}
pos = child;
}
arr[pos] = temp;
return min;
}
public int size() {
return currentSize;
}
public String toString() {
return Arrays.toString(arr);
}
public static void main(String[] args) {
BinaryHeap heap = new BinaryHeap();
heap.insert(1).insert(2).insert(3).insert(4).insert(6);
System.out.println(heap.toString());
System.out.println(heap.delete());
System.out.println(heap.toString());
heap.insert(5).insert(6);
System.out.println(heap.toString());
}
}
应用举例 (Fence Repair)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
BinaryHeap heap = new BinaryHeap();
int n = input.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = input.nextInt();
heap.insert(arr[i]);
}
int result = 0;
while (heap.size() > 1) {
// 取出最短和次短的木板
int min1 = heap.delete();
int min2 = heap.delete();
result += min1 + min2;
heap.insert(min1 + min2);
}
System.out.println(result);
}
}