[英]Dijkstra's Shortest Path algorithm not returning shortest path with smallest weight
[英]Djikstra's Shortest path algorithm
我正在学习 Djikstra,我根据与 Djikstra 略有不同的想法准备了下面的代码。 现在,在许多网站中,我已经看到使用 Extract min 和访问边缘的布尔数组。 我没有使用过,我的答案也是正确的。 是否有任何我的算法不起作用的测试用例或场景。
import java.util.*;
class ShortestPath2 {
static int Ar[][];
static int dist[];
static int nodes;
public static void djikstra(int source) {
LinkedList < Integer > list = new LinkedList < Integer > ();
dist[source] = 0;
list.add(source);
while (!list.isEmpty()) {
source = list.removeFirst();
for (int i = 0; i < nodes; i++) {
if (Ar[source][i] != 0) {
if (dist[i] > dist[source] + Ar[source][i]) {
dist[i] = Math.min(dist[i], dist[source] + Ar[source][i]);
list.add(i);
}
}
}
}
System.out.println(Arrays.toString(dist));
}
public static void main(String[] args) {
nodes = 9;
Ar = new int[nodes][nodes];
dist = new int[nodes];
Arrays.fill(dist, Integer.MAX_VALUE);
Ar = new int[][] {
{0, 4, 0, 0, 0, 0, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0},
{0, 0, 4, 14, 10, 0, 2, 0, 0},
{0, 0, 0, 0, 0, 2, 0, 1, 6},
{8, 11, 0, 0, 0, 0, 1, 0, 7},
{0, 0, 2, 0, 0, 0, 6, 7, 0}
};
djikstra(0);
}
}
Dijkstra 算法背后的整个想法是使用优先级队列。 您不能从 Dijkstra 中删除优先级队列并仍将其称为 Dijkstra 算法。 你写的是一个没有检查访问过的BFS。 如果图形具有负循环,您的代码将不会终止。 您的代码将在没有负循环的情况下找到图 a 上的最短路径,但复杂性可能会呈指数级增长。 因为有可能一遍又一遍地重新访问节点(由于删除了访问列表)。 如果您将访问列表添加到您的代码中,您的代码将不会总是找到最短路径,因为您没有使用优先级队列。 因此,您需要优先级队列和访问列表才能在线性时间内找到最短路径。
A --100---B --100-- I---100---O // A-B, B-I, I-O weight : 100
| / \ / \ | // A-C, C-D, ... weight : 1
C-D-E-F-G H-J-K-L M-N-P-Q-R
例如,您可以使用上图查看您的代码将重新访问O 的次数。
Dijkstra 的原始实现没有解决下降沿(但可以检测到)和负循环问题。
为了解决这个问题,我们可以使用 Bellman Ford 算法。
即使有负边缘(但没有负循环),它也会给出正确的最短路径
它可以检测是否存在负循环(但如果存在负循环,则不会给出正确的解决方案,因此我们最好终止代码)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.