//「最小堆」的实现
public class MinHeap {
// 使用数组创建完全二叉树的结构,然后使用二叉树构建一个「堆」
int[] minHeap;
// heapSize用于数组的大小,因为数组在创建的时候至少需要指明数组的元素个数
int heapSize;
// realSize用于记录「堆」的元素个数
int realSize = 0;
public MinHeap(int heapSize) {
this.heapSize = heapSize;
minHeap = new int[heapSize + 1];
// 为了便于完全二叉树的管理,数组的第0个索引的元素我们不会使用,请随便设置设置成任何一个值。
minHeap[0] = 0;
}
// 添加元素函数
public void add(int element) {
realSize++;
// 如果「堆」中元素的个数大于一开始设定的数组的个数,则返回「Add too many elements」
if (realSize > heapSize) {
System.out.println("Add too many elements!");
realSize--;
return;
}
// 将添加的元素添加到数组中
minHeap[realSize] = element;
// 新增元素的索引位置
int index = realSize;
// 新增元素的父节点的索引位置
// 注意,如果用数组表示完全二叉树,并且根结点存储在数组的索引1的位置的时候,任何一个节点的父节点索引位置为「该节点的索引位置/2」,任何一个节点的左孩子节点的索引位置为「该节点的索引位置*2」,任何一个节点的右孩子节点的索引位置为「该节点的索引位置*2+1」
int parent = index / 2;
// 当添加的元素小于父节点时,需要将父节点的值和新增元素的值交换
while ( minHeap[index] < minHeap[parent] && index > 1 ) {
int temp = minHeap[index];
minHeap[index] = minHeap[parent];
minHeap[parent] = temp;
index = parent;
parent = index / 2;
}
}
// 获取堆顶元素函数
public int peek() {
return minHeap[1];
}
// 删除堆顶元素函数
public int pop() {
// 如果当前「堆」的元素个数为0, 则返回「Don't have any element」
if (realSize < 1) {
System.out.println("Don't have any element!");
return Integer.MAX_VALUE;
} else {
// 当前「堆」中含有元素
// realSize >= 1
int removeElement = minHeap[1];
// 将「堆」中的最后一个元素赋值给堆顶元素
minHeap[1] = minHeap[realSize];
realSize--;
int index = 1;
// 当删除的元素不是孩子节点时
while (index < realSize && index <= realSize / 2) {
// 被删除节点的左孩子节点
int left = index * 2;
// 被删除节点的右孩子节点
int right = (index * 2) + 1;
// 当删除节点的元素大于 左孩子节点或者右孩子节点,代表该元素的值大,此时需要将该元素与左、右孩子节点中最小的值进行交换
if (minHeap[index] > minHeap[left] || minHeap[index] > minHeap[right]) {
if (minHeap[left] < minHeap[right]) {
int temp = minHeap[left];
minHeap[left] = minHeap[index];
minHeap[index] = temp;
index = left;
} else {
// maxHeap[left] >= maxHeap[right]
int temp = minHeap[right];
minHeap[right] = minHeap[index];
minHeap[index] = temp;
index = right;
}
} else {
break;
}
}
return removeElement;
}
}
// 返回「堆」的元素个数
public int size() {
return realSize;
}
public String toString() {
if (realSize == 0) {
return "No element!";
} else {
StringBuilder sb = new StringBuilder();
sb.append('[');
for (int i = 1; i <= realSize; i++) {
sb.append(minHeap[i]);
sb.append(',');
}
sb.deleteCharAt(sb.length() - 1);
sb.append(']');
return sb.toString();
}
}
public static void main(String[] args) {
// 测试用例
MinHeap minHeap = new MinHeap(3);
minHeap.add(3);
minHeap.add(1);
minHeap.add(2);
// [1,3,2]
System.out.println(minHeap.toString());
// 1
System.out.println(minHeap.peek());
// 1
System.out.println(minHeap.pop());
// [2, 3]
System.out.println(minHeap.toString());
minHeap.add(4);
// Add too mant elements
minHeap.add(5);
// [2,3,4]
System.out.println(minHeap.toString());
}
}