4

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

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

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

我在这里想念什么?

4

2 回答 2

8

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

我不认为有任何内在要求优先级队列是“稳定的”并且要求具有相同优先级的元素以相同的相对顺序出列,这与没有内在要求的方式大致相同排序算法是稳定的(尽管很多是稳定的)。这是一个不错的财产,但通常不能保证。这就是为什么标准堆排序不是稳定排序的原因。

幸运的是,将二进制堆调整为稳定并不难。保持与二进制堆关联的计数器。每当您将元素添加到堆中时,使用计数器的当前值标记它并增加计数器。在进行堆操作时,使用计数器作为决胜局来确定如果两个值比较相等,则哪个值更小。从本质上讲,这将比较更改为首先对实际值进行字典比较,然后对插入顺序进行比较。

希望这可以帮助!

于 2013-11-16T19:22:51.423 回答
0

简单的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();
        }
    }
}
于 2014-09-10T04:35:27.060 回答