繁体   English   中英

Djikstra 的最短路径算法

[英]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 算法。

  1. 即使有负边缘(但没有负循环),它也会给出正确的最短路径

  2. 它可以检测是否存在负循环(但如果存在负循环,则不会给出正确的解决方案,因此我们最好终止代码)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM