优先队列不工作

PriorityQueue not working

我正在尝试自己在 java 中实现 Dijkstra 算法。我有一个最小优先级队列,用于存储按当前最短路径排序的节点。

第一步很顺利,我将起始节点设置为距离0,其他设置为Integer.MAX_VALUE。起始节点已正确轮询。但是,在我删除第一个节点后,删除的第二个节点不是距离最小的节点。我不知道为什么。有意见吗?

这是我的代码

public void Dijkstra(Node s){
    initialize(s);
    List<Node> set = new ArrayList<Node>();
    Comparator<Node> c = new CompareNode();
    PriorityQueue<Node> Q = new PriorityQueue<Node>(V,c);
    for (Node q: Nodes){
        Q.add(q);
    }
    while (Q.size()!=0){
        Node u = Q.remove();
        System.out.println();
        System.out.println(u + " is removed with dis " + u.getD());
        set.add(u);
        for (Node w: u.getWeightedAdj().keySet()){
            relax(u,w);
        }
    }
}

public void initialize(Node s){
    for (Node v: Nodes){
        v.setD(Integer.MAX_VALUE);
        v.setPredecessor(null);
    }
    s.setD(0);
}

public void relax(Node u, Node w){
    if (w.getD()>u.getD()+u.getWeightedAdj().get(w)){
        w.setD(u.getD()+u.getWeightedAdj().get(w));
        w.setPredecessor(u);
    }
}

和比较器class

import java.util.Comparator;

public class CompareNode implements Comparator<Node> {

@Override
public int compare(Node o1, Node o2) {
    if (o1.getD()>o2.getD())
        return 1;
    if (o1.getD()<o2.getD())
        return -1;
    return 0;
    }
}

当我运行它的时候,结果是这样的

A is removed with dis 0

E is removed with dis 2147483647

C is removed with dis 2

D is removed with dis -2147483648

B is removed with dis 3

问题是 PriorityQueue 在添加元素时假定元素的顺序不能更改。

在您的示例中,当将节点添加到队列(起始节点除外)时,您的所有距离都是 MaxInt,因此它们以有效的随机顺序放入队列。

然后您调整距离,但 PriorityQueue 不知道这些调整,因此继续 return 原始顺序中的元素。

对此的标准做法是在距离发生变化时在优先级队列中插入元素。 (当一个元素从队列中移除时,需要测试是否已经访问过这个元素,因为同一个元素可以在队列中出现多次。)

发现节点后将其添加到队列中会更容易。 IE。一开始只添加根节点,然后在每次迭代中添加新发现的尚未处理的节点。在迭代步骤中,您需要检查队列中是否有新节点,如果新距离更短,则可能会更新它们。