我试图从维基百科页面上的Pseudocode实现Dijkstra算法。我在轮询Queue之后设置了一个条件,测试当前节点是否是目标节点,b。如果是这样,则算法将断开并返回从a到b的路径。
这个条件总是得到满足,因为我知道邻接矩阵范围内的所有节点确实存在。该计划旨在模拟伦敦地铁地图的连接。
无论如何,我一直试图弄清楚这一段时间,到目前为止它还没有找到我。也许有人可以发现这个问题。哦,adj
只是我图表的邻接矩阵。
/**
Implementation of Dijkstra's Algorithm taken from "Introduction to
Algorithms" by Cormen, Leiserson, Rivest and Stein. Third edition.
d = Array of all distances.
pi = Previous vertices.
S = Set of vertices whose final shortest path weights have been
determined.
Q = Priority queue of vertices.
**/
public ArrayList<Integer> dijkstra(Integer a, Integer b){
final double[] d = new double[adj.length];
int[] pi = new int[adj.length];
HashSet<Integer> S = new HashSet<Integer>();
PriorityQueue<Integer> Q = new PriorityQueue<Integer>(d.length, new Comparator<Integer>(){
public int compare(Integer a, Integer b){
Double dblA = d[a-1];
Double dblB = d[b-1];
return dblA.compareTo(dblB);
}
});
for(int i=0; i<d.length; i++){
d[i] = Double.POSITIVE_INFINITY;
}
d[a] = 0f;
for(int i=0; i<d.length; i++){
Q.add(i+1);
}
while(Q.size() > 0){
int u = Q.poll();
if(u == b){
System.out.println("jjd");
ArrayList<Integer> path = new ArrayList<Integer>();
for(int i=pi.length-1; i>=0; i--){
path.add(pi[i]);
}
return path;
}
S.add(u);
if(d[u] == Double.POSITIVE_INFINITY){
break;
}
for(int v=0; v<adj.length; v++){
double tmp = d[u] + adj[u][v];
if(tmp < d[v]){
d[v] = tmp;
pi[v] = u;
}
}
}
return new ArrayList<Integer>();
}
}
编辑: - 在做一些调试之后,看起来while循环的主体只执行一次。
答案 0 :(得分:2)
if(d[u] == Double.POSITIVE_INFINITY){
break;
}
for(int v=0; v<adj.length; v++){
double tmp = d[u] + adj[u][v];
if(tmp < d[v]){
d[v] = tmp;
pi[v] = u;
}
}
更改循环体中的d
值不会重新排列优先级队列,因此除非在弹出初始节点后碰巧位于队列顶部的元素是其邻居之一,你将在下一次迭代中获得d[u] == Double.POSITIVE_INFINITY
然后休息。
在Dijkstra的算法中,重要的是在节点距离改变时更新队列。 java.util.PriorityQueue<E>
不提供该功能,因此使用它是非常重要的,除了在每次更新时删除和重新添加更新的节点之外,我认为无法使用它。这当然不是很有效,因为删除是O(size)
。
通过不让队列中的所有节点都可以减轻低效率。仅添加初始节点的星形,并且在循环中,仅插入尚未看到的邻居,删除并重新插入已在队列中的邻居。这样可以缩短队列,使平均删除成本更低。
为了实现高效实施,您需要一个自定义优先级队列,以便更快地(O(log size)
?)更新优先级。
答案 1 :(得分:0)
如果从System.out.println运行程序时在控制台中输出'jjd',问题应该是:
if(u == b){
System.out.println("jjd");
ArrayList<Integer> path = new ArrayList<Integer>();
for(int i=pi.length-1; i>=0; i--){
path.add(pi[i]);
}
return path;
当您呼叫“返回路径”时;你实际上打破了整个方法并返回'path'。