尽管事实上我已经获得了计算机科学学士学位(这在大学里有所涉及),但我从来没有能够理解二进制堆和优先级队列之间的关系。它只是...没有点击。我完全理解二进制堆是什么,我知道如何在数组中实现一个。我也知道优先队列是什么。但是他们两个如何结合在一起呢?
快速谷歌查询显示了许多文章,如this one。哪种解释,但我还有更多问题:
我在这里缺少什么?
答案 0 :(得分:8)
优先级队列是一种抽象数据类型,如“stack”或“associative array”。可以有许多不同的方法来实现优先级队列 - 您可以使用二进制堆,二项式堆,Fibonacci堆,配对堆等。
我不认为优先级队列有任何内在要求是“稳定的”,并且要求具有相同优先级的元素以与添加它们相同的相对顺序出列,这与没有相同的方式相同排序算法稳定的内在要求(虽然很多)。这是一个不错的财产,但通常不保证。这就是为什么,例如,标准的堆不是一个稳定的类型。
幸运的是,调整二进制堆以保持稳定并不太难。保持与二进制堆相关联的计数器。每当向堆中添加元素时,使用计数器的当前值标记它并递增计数器。在执行堆操作时,使用计数器作为仲裁器,以确定如果两个值比较相等则哪个值更小。从本质上讲,这会将比较更改为首先根据实际值进行词典编制比较,然后再根据插入顺序进行比较。
希望这有帮助!
答案 1 :(得分: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();
}
}
}