PriorityQueue无效

时间:2017-05-04 12:02:19

标签: java algorithm dijkstra

我试图在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);
    }
}

比较器类

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

2 个答案:

答案 0 :(得分:0)

问题在于,在添加元素时,PriorityQueue会对元素进行排序,并假设订单无法更改。

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

然后调整距离,但PriorityQueue不知道这些调整,因此继续按原始顺序返回元素。

标准方法是在距离改变时在优先级队列中插入元素。 (当从队列中删除元素时,您需要测试您是否已访问过该元素,因为相同的元素可以在队列中多次出现。)

答案 1 :(得分:0)

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