算法系列-最短路径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算法求最短路径

相关推荐
啊阿狸不会拉杆17 分钟前
《机器学习导论》第 5 章-多元方法
人工智能·python·算法·机器学习·numpy·matplotlib·多元方法
R1nG8631 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
信码由缰1 小时前
Spring Boot 面试问题
spring boot·后端·面试
_OP_CHEN1 小时前
【算法基础篇】(五十六)容斥原理指南:从集合计数到算法实战,解决组合数学的 “重叠难题”!
算法·蓝桥杯·c/c++·组合数学·容斥原理·算法竞赛·acm/icpc
TracyCoder1231 小时前
LeetCode Hot100(27/100)——94. 二叉树的中序遍历
算法·leetcode
九.九2 小时前
CANN HCOMM 底层机制深度解析:集合通信算法实现、RoCE 网络协议栈优化与多级同步原语
网络·网络协议·算法
C++ 老炮儿的技术栈2 小时前
Qt Creator中不写代如何设置 QLabel的颜色
c语言·开发语言·c++·qt·算法
子春一2 小时前
Flutter for OpenHarmony:构建一个 Flutter 数字消消乐游戏,深入解析网格状态管理、合并算法与重力系统
算法·flutter·游戏
草履虫建模8 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq10 小时前
分布式系统安全通信
开发语言·c++·算法