📜  Dijkstra 的最短路径和最小边(1)

📅  最后修改于: 2023-12-03 15:30:27.237000             🧑  作者: Mango

Dijkstra 的最短路径和最小边

简介

Dijkstra 是一种找到无权图或者有权图中的最短路径的算法。它是一种使用了广度优先搜索(BFS)的方法来构造最短路径树的算法。

Dijkstra 算法的核心思想是从起点开始,不断地依次考察与起点相邻的节点,以构造一颗最短路径树。为了实现这个过程,我们需要记录每个节点到起点的距离值,以及每个节点的前一个节点(也就是在该节点前面的节点)。通过这种方式,我们就可以逐步地找到从起点到每个节点的最短路径,从而得到一颗最短路径树。

算法步骤

Dijkstra 算法的具体步骤如下:

  1. 将起点标记为已经访问,并将起点到起点的距离设置为 0。
  2. 构造一个空的集合 S,用来记录已经访问过的节点。
  3. 将起点加入集合 S。
  4. 对于所有与起点直接相邻的节点,更新这些节点到起点的距离,并记录它们的前一个节点为起点。也就是说,如果从起点到节点 i 这条路径的长度比之前记录的路径长度更小,那么更新这个距离,并且设置节点 i 的前一个节点为起点。
  5. 从集合 S 中选择一个距离起点最近的节点 j,并将节点 j 加入集合 S。
  6. 对于所有与节点 j 相邻的节点,计算从起点到这些节点的距离,并且如果这个距离比之前记录的距离更小,就更新这个距离,并将这个节点的前一个节点设置为节点 j。
  7. 重复步骤 5 和 6,直到所有的节点都被加入到集合 S 中。
  8. 最终,我们就可以得到起点到每个节点的最短路径,以及最短路径树。
程序示例

下面是一个使用 Java 实现的 Dijkstra 算法的示例代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Dijkstra {

    public static void main(String[] args) {
        int[][] graph = new int[][]{
                {0, 1, 4, 0, 0},
                {1, 0, 2, 5, 0},
                {4, 2, 0, 1, 5},
                {0, 5, 1, 0, 3},
                {0, 0, 5, 3, 0}
        };
        findShortestPath(graph, 0);
    }

    public static void findShortestPath(int[][] graph, int start) {
        int n = graph.length;

        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[start] = 0;

        boolean[] visited = new boolean[n];
        visited[start] = true;

        List<Integer> pathList = new ArrayList<>();
        pathList.add(start);

        for (int i = 0; i < n - 1; i++) {
            int minDist = Integer.MAX_VALUE;
            int minIdx = -1;

            for (int j = 0; j < n; j++) {
                if (!visited[j] && graph[pathList.get(pathList.size() - 1)][j] != 0) {
                    int newDist = dist[pathList.get(pathList.size() - 1)] + graph[pathList.get(pathList.size() - 1)][j];
                    if (newDist < dist[j]) {
                        dist[j] = newDist;
                    }
                    if (dist[j] < minDist) {
                        minDist = dist[j];
                        minIdx = j;
                    }
                }
            }

            visited[minIdx] = true;
            pathList.add(minIdx);
        }

        System.out.println("Shortest path from node " + start + " to other nodes are:");
        for (int i = 0; i < n; i++) {
            if (i != start) {
                System.out.println(start + " -> " + i + " : " + dist[i] + " (via " + pathList.get(pathList.indexOf(i) - 1) + ")");
            }
        }
    }
}

该程序接受一个邻接矩阵作为输入,并且将计算从起点到每个节点的最短路径,并输出结果。在这个示例中,邻接矩阵代表了一个无向图,其中的每个数字表示两个节点之间的距离。0 表示两个节点之间没有边相连。

结论

Dijkstra 算法是一种非常有效的算法,可以被用来解决一些实际问题,例如计算路由表等。虽然这个算法的时间复杂度不如其他算法(例如 Bellman-Ford 算法)那么优秀,但是,在大多数实际情况下,Dijkstra 算法能够在合理的时间内找到最短路径。