算法系列-最短路径Dijkstra算法和JAVA实现

Dijkstra算法是一种用于解决单源最短路径问题的经典算法,由荷兰计算机科学家Edsger W. Dijkstra于1956年提出。它可以找到从起始节点到所有其他节点的最短路径。

基本介绍

该算法的基本思想是通过逐步扩展节点的方式,逐渐确定从起始节点到其他节点的最短路径。算法维护两个集合:一个是已确定最短路径的节点集合,记为S;另一个是还未确定最短路径的节点集合,记为V-S。

算法步骤:

  1. 创建一个距离表,用于记录起始节点到各个节点的当前最短距离。起始节点的最短距离初始化为0,其他节点的最短距离初始化为无穷大(或一个很大的数)。

  2. 选择起始节点作为当前节点,并将其加入已确定最短路径的节点集合S。

  3. 对于当前节点的所有邻居节点,更新它们的最短距离。具体步骤如下:

    • 遍历当前节点的所有邻居节点。
    • 对于每个邻居节点,计算从起始节点经过当前节点到达该邻居节点的距离。如果该距离小于该邻居节点当前的最短距离,则更新最短距离。
  4. 从未确定最短路径的节点集合V-S中选择一个距离最小的节点作为新的当前节点,并将其加入已确定最短路径的节点集合S。

  5. 重复步骤3和步骤4,直到所有节点都被加入到已确定最短路径的节点集合S中,或者无法找到更短的路径。

  6. 最终,距离表中记录的即为起始节点到各个节点的最短距离。

Dijkstra算法的关键在于每次选择距离最小的节点作为当前节点,并通过更新邻居节点的最短距离来逐步扩展最短路径。该算法基于贪心策略,每次选择当前最优解,因此可以找到最短路径。

需要注意的是,Dijkstra算法要求图中的边权重非负,且对于有向图和无向图都适用。如果图中存在负权边,可以使用其他算法,如Bellman-Ford算法或SPFA算法来解决最短路径问题。

举例

以D为开头,求D到各个点的最短距离。

第1步:初始化距离,其实指与D直接连接的点的距离。dis[c]代表D到C点的最短距离,因而初始dis[C]=3,dis[E]=4,dis[D]=0,其余为无穷大。设置集合S 用来表示已经找到的最短路径。此时,S={D}。现在得到D到各点距离 {D(0),C(3),E(4),F(*),G(*),B(*),A(*)} ,其中*代表未知数也可以说是无穷大,括号里面的数值代表D点到该点的最短距离。

第2步:不考虑集合S中的值,因为dis[C]=3,是当中距离最短的,所以此时更新S,S={D,C} 。接着我们看与C连接的点,分别有B,E,F,已经在集合S中的不看 ,dis[C-B]=10,因而dis[B]=dis[C]+10=13,dis[F]=dis[C]+dis[C-F]=9,dis[E]=dis[C]+dis[C-E]=3+5=8>4 (初始化时的dis[E]=4) 不更新。此时 {D(0),C(3),E(4),F(9),G(*),B(13),A(*)}。

第3步:在第2步中,E点的值4最小,更新S={D,C,E} ,此时看与E点直接连接的点,分别有F,G。dis[F]=dis[E]+dis[E-F]=4+2=6(比原来的值小,得到更新 ),dis[G]=dis[E]+dis[E-G]=4+8=12(更新 )。此时 {D(0),C(3),E(4),F(6),G(12),B(13),A(*)}

第4步:在第3步中,F点的值6最小,更新S={D,C,E,F} ,此时看与F点直接连接的点,分别有B,A,G。dis[B]=dis[F]+dis[F-B]=6+7=13,dis[A]=dis[F]+dis[F-A]=6+16=22,dis[G]=dis[F]+dis[F-G]=6+9=15>12(不更新 )。此时 {D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

第5步:在第4步中,G点的值12最小,更新S={D,C,E,F,G} ,此时看与G点直接连接的点,只有A。dis[A]=dis[G]+dis[G-A]=12+14=26>22(不更新 )。 {D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

第6步:在第5步中,B点的值13最小,更新S={D,C,E,F,G,B} ,此时看与B点直接连接的点,只有A。dis[A]=dis[B]+dis[B-A]=13+12=25>22(不更新 )。 {D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

第6步:最后只剩下A值,直接进入集合S={D,C,E,F,G,B,A} ,此时所有的点都已经遍历结束,得到最终结果 {D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

JAVA实现

上述案例的JAVA实现

java 复制代码
import java.util.Arrays;

public class DijkstraAlgorithm {
    private static int minDistance(int[] dist, boolean[] visited) {
        int min = Integer.MAX_VALUE;
        int minIndex = -1;

        for (int i = 0; i < dist.length; i++) {
            if (!visited[i] && dist[i] <= min) {
                min = dist[i];
                minIndex = i;
            }
        }

        return minIndex;
    }

    private static void dijkstra(int[][] graph, int source) {
        int numVertices = graph.length;
        int[] dist = new int[numVertices];
        boolean[] visited = new boolean[numVertices];

        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[source] = 0;

        for (int count = 0; count < numVertices - 1; count++) {
            int u = minDistance(dist, visited);
            visited[u] = true;

            for (int v = 0; v < numVertices; v++) {
                if (!visited[v] && graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }

        System.out.println("Shortest distances from vertex " + source + ":");
        for (int i = 0; i < numVertices; i++) {
            System.out.println("Vertex " + i + ": " + dist[i]);
        }
    }

    public static void main(String[] args) {
        int[][] graph = {
            {0, 12, 0, 0, 0, 14, 16},
            {12, 0, 10, 0, 0, 0, 7},
            {0, 10, 0, 3, 5, 0, 6},
            {0, 0, 3, 0, 4, 0, 0},
            {0, 0, 5, 4, 0, 8, 2},
            {14, 0, 0, 0, 8, 0, 9},
            {16, 7, 6, 0, 2, 9, 0}
        };

        int source = 3; // Starting vertex

        dijkstra(graph, source);
    }
}

参考

1.图文详解 Dijkstra 最短路径算法

2.(七)通俗易懂理解------dijkstra算法求最短路径

相关推荐
用户405478783748243 分钟前
深度学习笔记 - 使用YOLOv5中的c3模块进行天气识别
算法
shinelord明1 小时前
【再谈设计模式】建造者模式~对象构建的指挥家
开发语言·数据结构·设计模式
十七算法实验室1 小时前
Matlab实现麻雀优化算法优化随机森林算法模型 (SSA-RF)(附源码)
算法·决策树·随机森林·机器学习·支持向量机·matlab·启发式算法
黑不拉几的小白兔1 小时前
PTA部分题目C++重练
开发语言·c++·算法
迷迭所归处1 小时前
动态规划 —— dp 问题-买卖股票的最佳时机IV
算法·动态规划
chordful1 小时前
Leetcode热题100-32 最长有效括号
c++·算法·leetcode·动态规划
_OLi_2 小时前
力扣 LeetCode 459. 重复的子字符串(Day4:字符串)
算法·leetcode·职场和发展·kmp
Romanticroom2 小时前
计算机23级数据结构上机实验(第3-4周)
数据结构·算法
白藏y2 小时前
数据结构——归并排序
数据结构·算法·排序算法
ahadee2 小时前
蓝桥杯每日真题 - 第12天
c++·vscode·算法·蓝桥杯