一、手动改写堆(非常重要)!
系统提供的堆无法做到的事情:
1)已经入堆的元素,如果参与排序的指标方法变化,
系统提供的堆无法做到时间复杂度O(logN)调整!都是O(N)的调整!
2)系统提供的堆只能弹出堆顶,做不到自由删除任何一个堆中的元素,
或者说,无法在时间复杂度O(logN)内完成!一定会高于O(logN)
根本原因:无反向索引表
二、加强堆的核心点
1)建立反向索引表indexMap
2)建立比较器
3)核心在于各种结构相互配合,非常容易出错
三、构建加强堆演示
package class07;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
/**
* 手写一个加强堆,比系统自带的优先队列多了更多高效的获取元素查询动作
* 注意泛型:T一定要是非基础类型,有基础类型需求包一层
*/
public class HeapGreaterTrain<T> {
//保存堆元素的集合
public ArrayList<T> heap;
//保存堆元素对应的索引位置 元素:索引
public HashMap<T, Integer> indexMap;
//堆大小
public int heapSize;
//比较器,自定义的比较器 ?匹配类型是T的父类 包括T本身
public Comparator<? super T> comp;
public HeapGreaterTrain(Comparator<? super T> c) {
heap = new ArrayList<>();
indexMap = new HashMap<T, Integer>();
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) {
//直接进集合最后,反向索引表创建关系,后面再接着insert向上排序
heap.add(obj);
indexMap.put(obj, heapSize);
heapInsert(heapSize++);
}
//堆向上交换操作,默认是小根堆的排序
private void heapInsert(int i) {
//通过业务创建加强堆自定义的比较器来定义排序,假设返回小于0,执行交换操作
while (comp.compare(heap.get(i), heap.get((i - 1) / 2)) < 0) {
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}
}
//出堆操作
public T pop(){
//出堆顶,然后与最后一个元素交换,再将最后一个元素从集合与反向索引表删除
T ans = heap.get(0);