小顶堆
小顶堆,用于最小优先队列的底层,且不进行多个堆合并的情况。常用于事件系统,关键字主要使用的是时间戳。
// 小顶堆的实现
public class Heap {
private long[] elements;
private int size = 0;
private int capacity = 8;
public Heap() {
elements = new long[capacity];
}
// 扩容
private void enrich() {
capacity = capacity + (capacity >> 1);
long[] temp = new long[capacity];
System.arraycopy(elements,0,temp,0,elements.length);
elements = temp;
}
// 添加一个元素
public void add(long data) {
// 容量不够,扩容为原来的3/2
if (size >= capacity) {
enrich();
}
int i = size;
elements[i] = data;
while (i>0 && elements[i]<=elements[(i-1)/2]) {
long temp = elements[i];
elements[i] = elements[(i-1)/2];
elements[(i-1)/2] = temp;
i = (i-1)/2;
}
size ++;
}
// 删除一个最小值并取出
public long rm() {
if (size == 0) {
throw new RuntimeException("堆为空,无法删除");
}
long result = elements[0];
elements[0] = elements[size-1];
elements[size-1] = result;
int i = 0;
while (i < (size-2)>>1) {
if (elements[2*i+1] <= elements[2*i+2]){
long temp1 = elements[2*i+1];
elements[2*i+1] = elements[i];
elements[i] = temp1;
i = 2*i+1;
} else {
long temp1 = elements[2*i+2];
elements[2*i+2] = elements[i];
elements[i] = temp1;
i = 2*i+2;
}
}
size --;
return result;
}
// 遍历堆数据结构
public void traverse() {
System.out.printf("[");
if (size != 0) {
Set<Integer> set = new HashSet<>();
System.out.printf("%d,", elements[0]);
set.add(0);
// 所有节点的左右孩子都遍历到才结束
while (set.size() != size){
// 从根节点开始
// 对所有已访问节点的左右孩子进行判断,
// 按层次进行扩散,
// 典型的dfs算法,
// 算法类似编译原理里NFA对字符串的判别方式
long min = Long.MAX_VALUE;
int minindex = -1;
for (Integer index : set) {
int left = index*2+1;
if (left < size && !set.contains(left) && elements[left]<min) {
min = elements[left];
minindex = left;
}
int right = index*2+2;
if (right < size && !set.contains(right) && elements[right]<min) {
min = elements[right];
minindex = right;
}
}
if (minindex != -1) {
System.out.printf("%d,", elements[minindex]);
set.add(minindex);
}
}
}
System.out.println("]");
}
// 遍历数组
public void all() {
for (int i = 0; i < size; i++) {
System.out.printf("%d,", elements[i]);
}
System.out.println();
}
}
// 测试
public class Main {
public static void main(String[] args) {
Heap heap = new Heap();
heap.add(0L);
heap.add(4L);
heap.add(3L);
heap.add(1L);
heap.add(2L);
heap.add(5L);
heap.add(8L);
heap.add(7L);
heap.add(6L);
heap.add(9L);
heap.all();
heap.traverse();
}
}