zoukankan      html  css  js  c++  java
  • 改变已知排序的key,依然保持大根堆或者小根堆


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

    /**
    * 改变已知排序的key,依然保持大根堆或者小根堆
    */
    public class ChangeSortKeyHeap {

    public static class MyHeap<T> {

    public ArrayList<T> heap;

    public HashMap<T, Integer> indexMap;

    public int heapSize;

    public Comparator<T> comp;

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

    public void push(T value) {
    if (contains(value)) {
    heap.set(indexMap.get(value), value);
    return;
    }
    heap.add(value);
    indexMap.put(value, heapSize);
    heapInsert(heapSize++);
    }

    public T pop() {
    if (isEmpty()) {
    System.out.println("the heap is empty");
    return null;
    }
    T res = heap.get(0);
    int end = heapSize - 1;
    swap(0, end);
    heap.remove(end);
    indexMap.remove(res);
    heapify(0, --heapSize);
    return res;
    }

    /**
    * 修改对象的key,并重新使有序
    *
    * @param value 对象
    */
    public void resign(T value) {
    if (!contains(value)) {
    System.out.println("the value is not in the heap");
    return;
    }
    int valueIndex = indexMap.get(value);
    heapInsert(valueIndex);
    heapify(valueIndex, heapSize);
    }

    /**
    * 修改了一个元素之后,保持原逻辑排序
    *
    * @param index 修改的元素位置
    * @param heapSize 堆大小
    */
    public void heapify(int index, int heapSize) {
    int left = (index << 1) + 1;
    while (left < heapSize) {
    int largest = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? left + 1 : left;
    if (comp.compare(heap.get(index), heap.get(largest)) <= 0) {
    break;
    }
    swap(index, largest);
    index = largest;
    left = (index << 1) + 1;
    }
    }

    /**
    * 往堆中添加一个元素,同时保持原逻辑排序
    *
    * @param index 新添加的元素的位置
    */
    public void heapInsert(int index) {
    int pIndex = 0;
    // 此处 ((index - 1) / 2) 和 ((index - 1) >> 1) 计算结果是不一样的,当index=0,前者是0,后者是-1
    while (comp.compare(heap.get(index), heap.get(pIndex = ((index - 1) / 2))) < 0) {
    swap(index, pIndex);
    index = pIndex;
    }
    }

    /**
    * 交换两个元素的位置
    *
    * @param i 位置
    * @param j 位置
    */
    private void swap(int i, int j) {
    // 同一个位置交换无意义
    if (i == j) {
    return;
    }
    // 交换
    T o1 = heap.get(i);
    T o2 = heap.get(j);
    heap.set(i, o2);
    heap.set(j, o1);
    indexMap.put(o1, j);
    indexMap.put(o2, i);
    }

    public int size() {
    return heapSize;
    }

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

    public boolean contains(T value) {
    if (isEmpty()) {
    return false;
    }
    return indexMap.containsKey(value);
    }

    }

    }

    /* 如有意见或建议,欢迎评论区留言;如发现代码有误,欢迎批评指正 */
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 奇偶判断
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Qt: 访问容器(三种方法,加上for循环就四种了)good
  • 原文地址:https://www.cnblogs.com/laydown/p/12819923.html
Copyright © 2011-2022 走看看