加强堆-堆结构的改写,增加反向索引表

什么是加强堆

以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();
    }
}

不了解堆排序的可以先看下这个堆排序的介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值