什么是加强堆
以java为例.系统提供的PriorityQueue(优先队列) 采用的是堆排序,默认是小根堆,只提供了基础的添加和弹出的方法.我们没法根据一个值查到他在堆结构中的位置,加强堆就是增加反向索引表.
直接上代码演示.
/**
* 加强堆
*/
public class HeapGreater<T> {
public int heapSize;
public ArrayList<T> heap;
//比较器
public Comparator<T> comp;
//反向索引表
public HashMap<T,Integer> indexHeap;
public HeapGreater(Comparator<T> comp) {
this.comp = comp;
heapSize = 0;
heap = new ArrayList();
indexHeap = new HashMap();
}
public T poll(){
T t = heap.get(0);
//将堆元素堆顶元素和最后一个值进行交换
swap(0,heapSize - 1);
//然后将最后一个值删掉
indexHeap.remove(--heapSize);
heap.remove(t);
//新换上来的值向下比较
heapfiy(0);
return t;
}
public void push(T val){
heap.add(val);
indexHeap.put(val,heapSize++);
//向上比较,完成堆结构
heapInsert(heapSize);
}
public void remove(T t){
//获取t的位置
Integer index = indexHeap.get(t);
//最后一位当成要替换的位置
T t1 = heap.get(heapSize - 1);
//把反向索引表中这个值删掉
indexHeap.remove(t);
//heap 删掉最后一个位置
heap.remove(--heapSize);
//判断要删的是不是最后一个.是的话,上面已经完成了,不是的话,还要进行下面操作
if (t1 != t){
heap.set(index,t1);
indexHeap.put(t1,index);
resign(index);
}
}
public void resign(int index){
heapInsert(index);
heapfiy(index);
}
public int size(){
return heapSize;
}
public boolean isEmpty(){
return heapSize == 0;
}
public void heapInsert(int index){
while (comp.compare(heap.get(index),heap.get((index - 1) / 2)) < 0){
swap(index,(index - 1)/2);
index = (index - 1) / 2;
}
}
public void heapfiy(int index){
int left = index * 2 + 1;
while (left < heapSize){
int minIndex = left + 1 < heapSize && comp.compare(heap.get(left+1),heap.get(left) ) < 0 ? left + 1 : left;
minIndex = comp.compare(heap.get(minIndex),heap.get(index)) < 0 ? minIndex : index;
if (index == minIndex){
break;
}
swap(index,minIndex);
index = minIndex;
left = index * 2 + 1;
}
}
public void swap(int i,int j){
T ti = heap.get(i);
T tj = heap.get(j);
heap.set(i,tj);
heap.set(j,ti);
indexHeap.put(ti,j);
indexHeap.put(tj,i);
}
public static void main(String[] args) {
new PriorityQueue();
}
}