加强堆与系统给的PriorityQueue不同的是,具备反向索引表。可以用logN的时间复杂度,实现删除堆内指定元素,可以用O(1)的时间复杂度实现查找元素位置以及确定元素是否存在。除此之外,这个堆可以传入比较器确定比较规则。
public class HeapGreater<T> {
private ArrayList<T> heap;
private HashMap<T, Integer> indexMap;
private int heapSize;
// ? super T 是指存的都是T的父类,如果取出就不知道是什么类
private Comparator<? super T> comp;
public HeapGreater(Comparator<T> c) {
heap = new ArrayList<>();
indexMap = new HashMap<>();
heapSize = 0;
comp = c;
}
public boolean isEmpty() {
return heapSize == 0;
}
public int size() {
return heapSize;
}
public boolean contains(T obj) {
return indexMap.containsKey(obj);
}
public T peek() {
return heap.get(0);
}
public void push(T obj) {
heap.add(obj);
indexMap.put(obj, heapSize); // 就多了这一句
heapInsert(heapSize++);
}
public T pop() {
T ans = heap.get(0);
swap(0, heapSize - 1);
indexMap.remove(ans); // 就多了这一句
heap.remove(--heapSize); // 不是数组了,所以不能swap时--heapSize
heapify(0);
return ans;
}
// 删除堆内指定元素
public void remove(T obj) {
T replace = heap.get(heapSize - 1); // 堆最后一个元素
int index = indexMap.get(obj); // 需要删除元素的索引
indexMap.remove(obj); // 索引表删除
heap.remove(--heapSize); // 记录过值了,直接删除
if (obj != replace) { // 如果要删除的就是最后一个元素,直接结束
heap.set(index, replace); // 把堆最后一个元素,替换掉当前元素
indexMap.put(replace, index); // 调整替换后元素的索引
resign(replace);
}
}
// 调整元素位置正确
public void resign(T obj) {
heapInsert(indexMap.get(obj));
heapify(indexMap.get(obj));
}
// 请返回堆上的所有元素
public List<T> getAllElements() {
List<T> ans = new ArrayList<>();
for (T c : heap) {
ans.add(c);
}
return ans;
}
private 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;
}
}
private void heapify(int index) {
int left = index * 2 + 1;
while (left < heapSize) {
int best = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? (left + 1) : left;
best = comp.compare(heap.get(best), heap.get(index)) < 0 ? best : index;
if (best == index) {
break;
}
swap(best, index);
index = best;
left = index * 2 + 1;
}
}
private void swap(int i, int j) {
T o1 = heap.get(i);
T o2 = heap.get(j);
heap.set(i, o2);
heap.set(j, o1);
indexMap.put(o2, i);
indexMap.put(o1, j);
}
}