我正在学习Djikstra,我根据与Djikstra略有不同的想法准备了以下代码。 现在,在许多网站中,我已经看到使用Extract min和boolean数组的访问边缘。 我没有使用过,我的回答也是正确的。是否存在我的算法无法工作的测试用例或场景。
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);
}
}
答案 0 :(得分:1)
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 的次数。
答案 1 :(得分:1)
Dijkstra的原始实现并没有解决负边缘(但可以检测到它)和负循环问题。
要解决此问题,我们可以使用Bellman Ford算法。
即使存在负边缘(但没有负循环),它也会给出正确的最短路径
它可以检测是否存在负循环(但如果存在负循环,则不能给出正确的解决方案,所以我们最好终止代码)