8.2:加强堆

文章介绍了一种增强的Java堆数据结构,通过添加HashMap实现反向索引,从而在节点值改变时能以O(logN)的时间复杂度进行调整。这种方法改进了系统自带堆的性能,允许更快地通过值查找索引并进行插入、删除和调整操作。
摘要由CSDN通过智能技术生成

8.2:加强堆

// 引入:
// java系统自带的堆,如果内部某个节点的数值突然增大或是突然的减小,会导致这个堆功能失效。如果想要调整变化的节点,时间复  // 杂度是NlogN(先遍历数组找到值改变的节点,然后再向上/下调整)。
// 系统自带的堆,我们只能通过index找到value,无法通过value找到其index.所以我们对其进行改良,加上反向索引表hashmap。
// 这样我们可以通过value找到其index,使调整的时间复杂度降到log N。
// 图1

图一:

在这里插入图片描述

图2:

在这里插入图片描述

package algorithmbasic.class8;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

// 加强堆
public class HeapGreater<T> {
    private ArrayList<T> heap;
    private int heapSize;
    private HashMap<T, Integer> indexMap;
    private Comparator<? super T> comp;

    public HeapGreater(Comparator<? super T> comp) {
        this.heap = new ArrayList<>();
        indexMap = new HashMap<>();
        this.heapSize = 0;
        this.comp = comp;
    }

    public boolean isEmpty() {
        return this.heapSize == 0;
    }

    public int size() {
        return this.heapSize;
    }

    public boolean contains(T obj) {
        return this.indexMap.containsKey(obj);
    }

    public T peek() {
        return this.heap.get(0);
    }

    // logN
    public void push(T obj) {
        heap.add(obj);
        indexMap.put(obj, heapSize);
        heapInsert(heapSize++);
    }

    // logN
    public void heapInsert(int index) {
        int father = (index - 1) / 2;
        while (this.comp.compare(heap.get(index), heap.get(father)) < 0) {
            // 注意交换的时候,ArrayList中的K V需要交换,HashMap中的K V也需要交换。
            swap(father, index);
            index = father;
            father = (index - 1) / 2;
        }
    }

    // logN
    public T pop() {
        T ans = heap.get(0);
        swap(0, --heapSize);
        indexMap.remove(ans);
        // 注意:其实Arraylist里面已经有一个heapsize这样的尾指针,这里我们自己定义的heapsize只是为了方便我们找到尾节		  点下标。
        // 真正意义上删除一个节点还是需要Arraylist里面的尾指针进行操作的。
        heap.remove(heapSize); // 真正的将尾节点删除。
        heapFiy(0);
        return ans;
    }

    // logN
    public void heapFiy(int index) {
        int l = index * 2 + 1;
        while (l < heapSize) {
            int minSonIndex = l + 1 < heapSize ? (this.comp.compare(heap.get(l), heap.get(l + 1)) < 0 ? l : l + 1) : (l);
            if(this.comp.compare(heap.get(minSonIndex), heap.get(index)) < 0) {
                swap(minSonIndex, index);
                index = minSonIndex;
                l = index * 2 + 1;
            }else {
                break;
            }
        }
    }

    // logN
    public void remove(T obj) {
        // 得到节点的位置index
        int index = indexMap.get(obj);
        // 得到末尾的数 value
        T replace = heap.get(--heapSize);
        // 将hashmap中obj值以及heap中末尾的数直接删掉
        indexMap.remove(obj);
        // 真正的删除尾节点。
        heap.remove(heapSize);
        // 如果末尾节点值与obj是同一个,不需要一下操作
        if (obj != replace) {
            // 将结果塞回去
            heap.set(index, replace);
            indexMap.put(replace, index);
            resign(replace);
        }
    }

    // 重构造
    // 只会执行其中的一个,logN
    public void resign(T obj) {
        heapInsert(indexMap.get(obj));
        heapFiy(indexMap.get(obj));
    }

    // 请返回堆上的所有元素
    public List<T> getAllElements() {
        List<T> ans = new ArrayList<>();
        for (T c : heap) {
            ans.add(c);
        }
        return ans;
    }

    public void swap(int i, int j) {
        T value1 = heap.get(i);
        T value2 = heap.get(j);
        heap.set(i, value2);
        heap.set(j, value1);
        // HashMap新的值覆盖旧的值
        indexMap.put(value1, j);
        indexMap.put(value2, i);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackerTerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值