Algorithm 如何使用二进制堆实现优先级队列?

Algorithm 如何使用二进制堆实现优先级队列?,algorithm,data-structures,heap,priority-queue,binary-heap,Algorithm,Data Structures,Heap,Priority Queue,Binary Heap,尽管我获得了计算机科学学士学位(这在大学里也有涉及),但我始终无法理解二进制堆和优先级队列之间的关系。它只是。。。不点击。我完全理解什么是二进制堆,并且知道如何在数组中实现二进制堆。我还知道什么是优先级队列。但是他们两个是如何结合在一起的呢 一个快速的谷歌查询会显示很多类似的文章。哪种解释,但我还有更多的问题: 优先级队列需要确保,如果添加了两个具有相同优先级的项,那么它们将按照添加顺序被删除。二进制堆如何确保这一点?(事实上,如果我没有弄错的话,那么所有项具有相同优先级的边界情况将产生一个违反

尽管我获得了计算机科学学士学位(这在大学里也有涉及),但我始终无法理解二进制堆和优先级队列之间的关系。它只是。。。不点击。我完全理解什么是二进制堆,并且知道如何在数组中实现二进制堆。我还知道什么是优先级队列。但是他们两个是如何结合在一起的呢

一个快速的谷歌查询会显示很多类似的文章。哪种解释,但我还有更多的问题:

  • 优先级队列需要确保,如果添加了两个具有相同优先级的项,那么它们将按照添加顺序被删除。二进制堆如何确保这一点?(事实上,如果我没有弄错的话,那么所有项具有相同优先级的边界情况将产生一个违反此规则的堆)
  • 当您从堆中删除根,然后放入最后一个元素代替根,然后需要将其与其中一个子元素交换时会发生什么情况?但是两个子元素的值相同。如何选择要交换的设备?(记住相同优先项目的先进先出规则)

  • 这里我遗漏了什么?

    优先级队列是一种抽象的数据类型,如“堆栈”或“关联数组”。实现优先级队列可以有许多不同的方法-可以使用二进制堆、二项式堆、斐波那契堆、配对堆等

    我不认为有任何内在要求优先级队列是“稳定”的,也不要求具有相同优先级的元素以添加它们时的相同相对顺序退出队列,就像没有内在要求排序算法是稳定的一样(尽管许多是稳定的)。这是一个很好的财产,但通常不能保证。例如,这就是为什么标准堆不是一个稳定的排序

    幸运的是,调整二进制堆使其稳定并不太难。保留一个与二进制堆关联的计数器。无论何时向堆中添加元素,都要用计数器的当前值标记它并递增计数器。在执行堆操作时,将计数器用作分段符,以确定两个值比较相等时哪个值较小。从本质上讲,这会将比较更改为字典形式的比较,首先是对实际值的比较,然后是对插入顺序的比较


    希望这有帮助

    演示优先级队列的简单java代码

    package heap;
    
    import java.util.Comparator;
    
    /**
     * Generic implementation of priority queue based on heap with add and pop
     * Reverse is min heap
     *  Average Worst case
     Space  O(n)    O(n)
     Search O(n)    O(n)
     Insert O(1)    O(log n)
     Delete O(log n)    O(log n)
     * Created by  on 9/7/14.
     */
    public class BinaryHeap<T extends Comparable> {
        private final Comparable[] pq;
        private int size = 0;
    
        private final Comparator<Comparable> comparator;
    
        private final static Comparator<Comparable> comparatorMax = new Comparator<Comparable>() {
            @Override
            public int compare(Comparable o1, Comparable o2) {
                return o1.compareTo(o2);
            }
        };
    
    
        public BinaryHeap(int size) {
            this(size,false);
        }
    
        public BinaryHeap(int size, boolean reverse) {
            pq = new Comparable[size];
    
            if(reverse)
                comparator = comparatorMax.reversed();
            else
                comparator = comparatorMax;
        }
    
    
        public void add(T entry) throws Exception {
            if(size == pq.length)
                throw new Exception("Heap Overflow Exception: "+ entry);
            pq[size] = entry;
            size++;
            maxHeapify(pq, getNewPos(size - 1), true);
            print();
        }
    
        public Comparable pop() throws Exception {
            if(size == 0)
                return null;
            size--;
            swap(pq,0,size);
            Comparable entry = pq[size];
            pq[size] = null;
            maxHeapify(pq, 0, false);
            System.out.println("Popped: "+ entry);
            print();
            return entry;
        }
    
        public Comparable find(T entry) {
            for(int i=0; i < size; i++)
                if(comparator.compare(entry,pq[i]) == 0)
                    return entry;
    
            return null;
        }
    
        private void maxHeapify(Comparable[] entries, int pos, boolean swimUp) throws Exception {
            int leftPos = 2 * pos + 1;
            int rightPos = 2 * pos + 2;
    
            Comparable parent = entries[pos];
            Comparable left = null;
            if(leftPos < size)
                left = entries[leftPos];
    
            Comparable right = null;
    
            if(rightPos < size)
                right = entries[rightPos];
    
            if(left == null && right == null)
                return; //For swim Down case
    
            if (parent == null)
                throw new Exception("Entry not found Exception: " + pos);
    
            //Find the largest of left and right for swaps
            int largest = pos;
            if (left != null && comparator.compare(parent,left) < 0) {
                largest = leftPos;
            }
    
            if (right != null && comparator.compare(parent,right) < 0) {
                if(largest == pos)
                    largest = rightPos;
                else if(comparator.compare(right,entries[largest]) > 0) {
                    largest = rightPos;
                }
    
            }
    
            if (largest != pos) {
                swap(entries, largest, pos);
                if (swimUp && pos == 0)
                    return;
    
                maxHeapify(entries, swimUp ? getNewPos(pos) : largest, swimUp);
            }
        }
    
    
        private void swap(Comparable[] entries, int pos1, int pos2) {
            Comparable temp = entries[pos2];
            entries[pos2] = entries[pos1];
            entries[pos1] = temp;
        }
    
        private int getNewPos(int pos) {
            int newPos = pos / 2;//Takes the floor automatically because of int
            if (pos > 0 && pos % 2 == 0)
                newPos = (pos / 2) - 1;
    
            return newPos;
        }
    
        public void print() {
            System.out.print("[");
            int i=0;
            for(;i < size-1; i++)
                System.out.print(pq[i] + ",");
    
            System.out.print(pq[i]+"]");
            System.out.println();
        }
    
        public static void main(String[] args) {
            BinaryHeap<Integer> pq = new BinaryHeap<Integer>(100);
            try {
                pq.add(5);
    
                pq.add(3);
    
                pq.add(9);
    
                pq.add(16);
                pq.add(2);
                pq.add(3);
                pq.add(19);
                pq.add(500);
                pq.add(90);
                pq.add(1);
                pq.add(91);
                pq.add(600);
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
                pq.pop();
    
    
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    包堆;
    导入java.util.Comparator;
    /**
    *基于add和pop的堆优先级队列的通用实现
    *相反是最小堆
    *平均最坏情况
    空间O(n)O(n)
    搜索O(n)O(n)
    插入O(1)O(日志n)
    删除O(日志n)O(日志n)
    *创建于2014年9月7日。
    */
    公共类二进制堆{
    私人最终可比[]pq;
    私有整数大小=0;
    私人最终比较人;
    私有最终静态比较器comparatorMax=新比较器(){
    @凌驾
    公共整数比较(可比o1,可比o2){
    返回o1。与(o2)相比;
    }
    };
    公共二进制堆(整数大小){
    这个(大小,错误);
    }
    公共二进制堆(整数大小,布尔值反向){
    pq=新的可比[尺寸];
    如果(反向)
    比较器=比较器最大反向();
    其他的
    比较器=比较器最大值;
    }
    公共void add(T条目)引发异常{
    如果(尺寸=pq.长度)
    抛出新异常(“堆溢出异常:+条目”);
    pq[尺寸]=入口;
    大小++;
    maxHeapify(pq,getNewPos(尺寸-1),真);
    打印();
    }
    public()引发异常{
    如果(大小==0)
    返回null;
    大小--;
    交换(pq,0,大小);
    可比分录=pq[尺寸];
    pq[大小]=空;
    maxHeapify(pq,0,假);
    System.out.println(“弹出:+输入”);
    打印();
    返回条目;
    }
    公共可比发现(T项){
    对于(int i=0;i0){
    最大=右位;
    }
    }
    如果(最大!=位置){
    交换(分录、最大、pos);
    如果(swimUp&pos==0)
    返回;
    maxHeapify(条目,swimUp?getNewPos(pos):最大,swimUp);
    }
    }
    私有无效掉期(可比[]分录,整数pos1,整数pos2){
    可比温度=分录[pos2];
    条目[pos2]=条目[pos1];
    条目[pos1]=临时;
    }
    私有int getNewPos(int pos){
    int newPos=pos/2;//由于int而自动发言
    如果(位置>0和位置%2==0)
    newPos=(pos/2)-1;
    返回newPos;
    }
    公开作废印刷品(){
    系统输出打印(“[”);
    int i=0;
    对于(;i