Dijkstra算法解析及Java代码实现(附图)

图论:Dijkstra算法——最详细的分析,图文并茂,一次看懂! Dijstra算法 阅读详情

所谓单源,即求从一个点出发,到其他各点的最短路径,也就是说 :如果这个图有 n个点,我们要求 n-1个路径。

 

算法概述

Dijkstra算法使用了广度优先搜索(BFS)解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。

该算法的时间复杂度是n的平方,可以使用堆优化。

但是,要注意一点,Dijkstra算法只能适用于权值为正的情况下;如果权值存在负数,则不能使用。
 

算法基本思想

     通过Dijkstra计算图G中的最短路径时,需要指定起点vs(即从顶点vs开始计算)。

     此外,引进两个集合S和U。

  • S的作用:记录已求出最短路径的顶点
  • U的作用:记录还未求出最短路径的顶点(以及该顶点到起点vs的距离)。

     初始时,S 中只有起点 vs;U 中是除 vs 之外的其他顶点,并且 U 中顶点的路径是"起点vs到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到 S 中;接着,更新 U 中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。


算法具体操作步骤

(1) 初始时,S只包含起点 vs;U 包含除 vs 外的其他顶点,且U中顶点的距离为"起点vs到该顶点的距离"。

     例如,U中顶点v的距离为 (vs,v) 的长度,然后 vs 和 v 不相邻,则 v 的距离为∞。

(2) 从 U 中选出"距离最短的顶点 k",并将顶点 k 加入到 S 中;同时,从 U 中移除顶点 k。

(3) 更新 U 中各个顶点到起点 vs 的距离。之所以更新 U 中顶点的距离,是由于上一步中确定了 k 是求出最短路径的顶点,从而可以利用 k 来更新其它顶点的距离;例如,(vs,v) 的距离可能大于 (vs,k)+(k,v) 的距离。

(4) 重复步骤(2)和(3),直到遍历完所有顶点。

图示:这里的起点 vs 是 顶点D

伪代码:

代码:

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

public class ShortestPathDijkstra {
    /** 邻接矩阵 */
    private int[][] matrix;
    /** 表示正无穷 */
    private int MAX_WEIGHT = Integer.MAX_VALUE;
    /** 顶点集合 */
    private String[] vertexes;
 
    /**
     * 创建图2
     */
    private void createGraph2(int index) {
        matrix = new int[index][index];
        vertexes = new String[index];
        
        int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };
        int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };
        int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };
        int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };
        int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };
        int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };
        matrix[0] = v0;
        matrix[1] = v1;
        matrix[2] = v2;
        matrix[3] = v3;
        matrix[4] = v4;
        matrix[5] = v5;
        matrix[6] = v6;
        matrix[7] = v7;
        matrix[8] = v8;
        
        vertexes[0] = "v0";
        vertexes[1] = "v1";
        vertexes[2] = "v2";
        vertexes[3] = "v3";
        vertexes[4] = "v4";
        vertexes[5] = "v5";
        vertexes[6] = "v6";
        vertexes[7] = "v7";
        vertexes[8] = "v8";
    }
    
    /**
     * 创建图1
     */
    private void createGraph1(int index) {
        matrix = new int[index][index];
        vertexes = new String[index];
 
        int[] v0 = { 0, 1, MAX_WEIGHT, MAX_WEIGHT, 2, MAX_WEIGHT };
        int[] v1 = { 1, 0, 1, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v2 = { MAX_WEIGHT, 1, 0, 1, MAX_WEIGHT, MAX_WEIGHT };
        int[] v3 = { MAX_WEIGHT, MAX_WEIGHT, 1, 0, 1, MAX_WEIGHT };
        int[] v4 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 1, 0, 1 };
        int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 1, 1, 0 };
 
        matrix[0] = v0;
        matrix[1] = v1;
        matrix[2] = v2;
        matrix[3] = v3;
        matrix[4] = v4;
        matrix[5] = v5;
 
        vertexes[0] = "A";
        vertexes[1] = "B";
        vertexes[2] = "C";
        vertexes[3] = "D";
        vertexes[4] = "E";
        vertexes[5] = "F";
    }
 
    /**
     * Dijkstra最短路径。
     * 
     * vs -- 起始顶点(start vertex) 即,统计图中"顶点vs"到其它各个顶点的最短路径。
     */
    public void dijkstra(int vs) {
        // 建立flag数组, 长度为顶点数目, flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
        boolean[] flag = new boolean[vertexes.length];
        // S集合:记录已求出最短路径的顶点
        String[] S = new String[vertexes.length];
        // U集合:记录还未求出最短路径的顶点(以及该顶点到起点s的距离),与 flag配合使用,flag[i] == true 表示U中i顶点已被移除
        int[] U = new int[vertexes.length];
        // 前驱顶点数组,即:prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那些顶点。
        int[] prev = new int[vertexes.length];
        
 
        // 步骤一:初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。
        for (int i = 0; i < vertexes.length; i++) {
            flag[i] = false; // 顶点i的最短路径还没获取到(初始化为false)。
            U[i] = matrix[vs][i]; // 顶点i与顶点vs的初始距离为"顶点vs"到"顶点i"的权。也就是邻接矩阵vs行的数据。
            
            prev[i] = 0; //顶点i的前驱顶点为0
        }
 
        // 将vs从U中“移除”(U与flag配合使用)
        flag[vs] = true;  //flag[i] == true 表示U中i顶点已被移除
        U[vs] = 0;  //起点和自己本身的距离是0
        // 将vs顶点加入S
        S[0] = vertexes[vs];
        // 步骤一结束
        
        //步骤四:重复步骤二三,直到遍历完所有顶点。
        // 遍历vertexes.length-1次;每次找出一个顶点的最短路径。
        int k = 0;
        for (int i = 1; i < vertexes.length; i++) {
            // 步骤二:从U中找出路径最短的顶点,并将其加入到S中(如果vs顶点到x顶点还有更短的路径的话,
            // 那么必然会有一个y顶点到vs顶点的路径比前者更短且没有加入S中
            // 所以,U中路径最短顶点的路径就是该顶点的最短路径)
            // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
            int min = MAX_WEIGHT;
            for (int j = 0; j < vertexes.length; j++) {
                if (flag[j] == false && U[j] < min) {
                    min = U[j];
                    k = j;
                }
            }
            
            //将k放入S中
            S[i] = vertexes[k];
            
            //步骤二结束
            
            
            //步骤三:更新U中的顶点和顶点对应的路径
            //标记"顶点k"为已经获取到最短路径(更新U中的顶点,即将k顶点对应的flag标记为true)
            flag[k] = true;
            
            //修正当前最短路径和前驱顶点(更新U中剩余顶点对应的路径)
            //即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
            for (int j = 0; j < vertexes.length; j++) {
                //以k顶点所在位置连线其他顶点,判断其他顶点经过最短路径顶点k到达vs顶点是否小于目前的最短路径,是,更新入U,不是,不做处理
                int tmp = (matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]));
                if (flag[j] == false && (tmp < U[j])) {
                    U[j] = tmp;
                    //更新 j顶点的最短路径前驱顶点为k
                    prev[j] = k;
                }
            }
            //步骤三结束
        }
        //步骤四结束
 
        // 打印dijkstra最短路径的结果
        System.out.println("起始顶点:" + vertexes[vs]);
        for (int i = 0; i < vertexes.length; i++) {
            System.out.print("最短路径(" + vertexes[vs] + "," + vertexes[i] + "):" + U[i] + "  ");
            
            List<String> path = new ArrayList<>();
            int j = i;
            while (true) {
                path.add(vertexes[j]);
                
                if (j == 0)
                    break;
                
                j = prev[j];
            }
            
            for (int x = path.size()-1; x >= 0; x--) {
                if (x == 0) {
                    System.out.println(path.get(x));
                } else {
                    System.out.print(path.get(x) + "->");
                }
            }
            
        }
        
        System.out.println("顶点放入S中的顺序:");
        for (int i = 0; i< vertexes.length; i++) {
            
            System.out.print(S[i]);
            
            if (i != vertexes.length-1) 
                System.out.print("-->");
        }
            
    }
 
    public static void main(String[] args) {
        ShortestPathDijkstra dij = new ShortestPathDijkstra();
//        dij.createGraph1(6);
        dij.createGraph2(9);
        dij.dijkstra(0);
    }
 
}

其中代码中所调用的两张图片:

图一:

图二:

结果:

图一:

图二:

Dijkstra算法图文详解 Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 这样一个有权图,Dijkstra算法可以计算任意节点到其他节点的最短 阅读详情

相关推荐

算法详解——Dijkstra算法

Dijkstra算法的目的是寻找单起点最短路径,其策略是贪心加非负加权队列。

python_plus的博客 3726

狄克斯特拉(Dijkstra)算法详解

最近在看《算法图解》,其中第七章狄克斯特拉算法个人感觉并没有讲的清楚,比如看完7.1节给人的感觉是狄克斯特拉算法会遍历图中的每一条边,后续狄克斯特拉不适用负权边的说法就站不住脚了。后续在查阅诸多资料之后,总结文章一篇,尽可能以通俗易懂且思路清晰的方式来讲解狄克斯特拉算法。...

Wopelo的博客 4万+

【路径规划】(1) Dijkstra 算法求解最短路,附python完整代码

Dijkstra 算法是典型的单源最短路径计算算法,用于解决源点到其它所有点之间的最短路径计算的问题。它采用了贪心的思想搜索全局,求取最优解。算法优点:鉴于 Dijkstra 算法的全局遍历性,其计算结果准确性非常高,Dijkstra 算法可以避开局部最优陷阱,100%的求解出最优路径。

博观而约取,厚积而薄发 1万+

java实现Dijkstra算法

解决的问题: 求解单源最短路径,即各个节点到达源点的最短路径或权值 考察其他所有节点到远点的最短路径和长度 局限性: 无法解决权值为负数的情况参数:Dijkstra算法步骤: (1)初始化: 顶点集S: 顶点A到自已的最短路径长度为0。只包含源点,即S={A} 顶点集U: 包含除v0外的其他顶点. 即U={B,C,D,E,F} dist[]: 源点还不能到达的节点,其权值为∞path[]: 记录当前节点的前驱节点下标(源点还不能到达的节点为-1)(2)从U中选取一个节点,它是源点A到然后把加入S中(此.

欢迎来到烟火气知识小天地!这里记录生活、工作中的 “小麻烦”,从软件故障到生活难题,我会毫无保留分享解决思路与方法,愿成为你排忧解难时的温暖参考,伴你在解决问题路上稳步前行。 8579

Java实现Dijkstra算法

在dijkstra方法中,我们首先初始化起始节点到其他节点的距离为正无穷大,然后将起始节点的距离值设为0,并加入优先队列中。接下来,我们不断从队列中取出距离值最小的节点,更新其相邻节点的距离值,直到队列为空。该类包含顶点和边的信息。它的主要思想是通过不断更新起始节点到其他节点的距离值,逐步找到最短路径。在上述代码中,我们使用了一个优先队列来存储待处理的节点,并根据距离值进行排序。同时,我们使用一个列表来记录起始节点到各个节点的距离值。在上述代码中,我们创建了一个包含5个顶点的图,并添加了各个顶点之间的边。

HackMasterX的博客 199

Dijkstra算法的Java实现及应用

希望本文对你有所帮助!Dijkstra算法的基本原理是,通过不断遍历未确定最短路径的节点,以逐步更新各个节点的最短路径值,从而找到从源节点到其他所有节点的最短路径。创建一个距离数组dist[],用于存储从源节点到各个节点的当前最短距离,初始化dist[]中的值为正无穷大,表示暂时未能确定最短路径;b. 遍历与节点u相邻的节点v,并计算从源节点到节点v的距离newDistance,即dist[u]加上节点u到节点v的边的权值;循环结束后,dist[]中存储的就是从源节点到其他所有节点的最短路径值。

2301_79331328的博客 421

【数据结构与算法】java有向带权图最短路径算法-Dijkstra算法(通俗易懂)

有向图最段路径原理及java代码实现

Hanson的博客 3337

从0到1搭建StarRocks3.4.1存算一体架构(VM 虚拟机版)

本文详细介绍了如何在VM虚拟机上从零搭建StarRocks 3.4.1存算一体架构。首先阐述了StarRocks作为高性能分布式SQL数据仓库的优势,重点讲解了其存算一体架构的设计原理。随后提供完整的安装指南,包括环境准备(3台CentOS 8虚拟机配置)、网络互通验证、Java环境配置、软件包解压安装等关键步骤。文章特别详细说明了FE和BE节点的配置文件修改(fe.conf和be.conf)以及必要的防火墙端口开放配置。通过图文并茂的方式,帮助开发者和运维人员快速掌握StarRocks集群部署方法,为后续

小 tom的博客 1329

java dijkstra算法 指定源宿_一种基于双代价的优化路由方法与流程

本发明属于通信网技术领域。具体涉及一种基于双代价的优化路由方法。背景技术:为了在通信网络中的任意两个节点间建立业务连接,需要寻找一条最小代价通路作为业务路由。传统的网络路由算法,如Dijkstra最短路算法等,由于步骤简单,易操作,以及良好的可扩展性,在通信网领域得到大量的应用。传统的Dijkstra算法采用贪婪算法模式,通过链路代价累和的方式求得代价和最小的通路作为最短路径。在概率风险模型下,我...

weixin_32014283的博客 178

零代码搭建专业知识库:Wiki.js+cpolar让团队协作像写笔记一样简单

"项目文档又找不到了!“团队负责人小张第N次在群里看到这样的抱怨——技术文档分散在邮件、网盘和个人电脑里,新人入职要花一周熟悉文档位置,远程协作时版本混乱更是家常便饭。Wiki.js与cpolar内网穿透服务的出现,就像给团队协作装上了"中央大脑”,用写Markdown笔记的简单方式,搭建一个专业的知识库系统。普通人对知识管理的需求其实很简单:方便记录、容易查找、大家能用。但传统方案把这个过程搞得异常复杂:建服务器、配环境、学语法、搞权限……大部分团队还没开始就放弃了。

Yawesh的博客 2040

STM32实战:如何用GPS信号同时同步海康摄像头和Livox Mid-360雷达(附完整接线图)

本文详细介绍了如何利用STM32实现GPS信号分频,同步海康摄像头和Livox Mid-360雷达的时间同步方案。通过硬件架构设计、STM32信号处理核心实现及设备接口规范,解决了多传感器数据融合中的时间对齐难题,适用于自动驾驶和机器人导航领域。

weixin_29182481的博客 596

20162327 《程序设计与数据结构》第十一周学习总结

20162327 2017-2018-1 《程序设计与数据结构》第十一周学习总结 教材学习内容总结 1、在无向图中,表示边的顶点对是无序的 2、如果图中的两个顶点之间有边连接,则称它们是邻接的 3、如果无向图中的连接顶点的边数达到最大,则图为完全图 4、路径是图中连接顶点的边的序列 5、有向图中,边是顶点的有序对 6、有向图中的路径是连接两个顶点的有向边的序列 7、图的每条边上都有对应...

abc602375078的博客 240

实战案例:用多智能体系统模拟房地产市场的架构设计

房地产市场是典型的复杂自适应系统:买方纠结“要不要上车”、卖方盘算“挂多少钱能快速成交”、中介忙着“撮合两边赚佣金”、政府琢磨“怎么调政策稳房价”——每一个参与者的微小决策,最终都会汇聚成“房价暴涨”“成交冰点”这样的宏观现象。传统的计量经济学模型(比如线性回归)假设“所有人都是理性人”,但现实中没人能算清所有变量——你可能因为“同事买了学区房”就跟风,也可能因为“怕失业”而放弃买房。这时候,多智能体系统(MAS)

移动开发前沿的博客 1122

【最短路径算法】一文掌握Dijkstra算法,详解与应用示例+代码

Dijkstra算法(迪杰斯特拉算法)是一种用于在加权图中查找从一个起始节点到所有其他节点的最短路径的算法。该算法最初由荷兰计算机科学家Edsger W. Dijkstra于1956年提出。Dijkstra算法适用于带有非负权重的有向图或无向图。log(V)),其中V是节点数。如果使用优先队列来优化,时间复杂度可以减小到O(EDijkstra算法在许多领域广泛应用,包括路线规划、网络路由、资源分配和许多其他需要找到最短路径的应用。

qq_35831906的博客 2万+

VSCode玩转STM32:手把手教你配置EIDE插件与OpenOCD调试(附野火DAP配置文件详解)

本文详细介绍了如何在VSCode中配置EIDE插件与OpenOCD进行STM32开发,特别针对野火DAP调试器提供了配置文件详解。从基础环境搭建到深度调试技巧,帮助开发者高效完成STM32项目开发,实现现代化嵌入式开发工作流。

weixin_26905487的博客 553

智能车图像处理19-进阶篇11--斜入十字补线

这篇文章主要讲述智能车竞赛中如何对于斜入十字进行补线操作。

taiyuezyh的博客 7488

Dijkstra算法实现(java),从建立有向图开始!

手动写入节点,注意要按顺序写,因为节点的姓名和权值关系很大,不能跳着写,这里我加了判断,有兴趣的小伙伴可以适当改进,邻接矩阵大小可以设的很大,就不怕溢出了,这里我只设了6。之后是节点之间的相连并设置权值大小,这里我直接用的某视频的值写入了,这里可以写进方法里,博主比较懒,直接写主函数里了(运行结果图,写入的值我直接给你了,省的你在写(我这么好,不给个赞说不过去吧(doge))那么废话不多说,开始建立有向图,建立图节点,对象有三个,代码注释了。主要特点是以起始点为中心向外,层层扩展,直到扩展覆盖所有顶点。

qq_57211285的博客 1010

【数据集】MODIS 的 MOD07 大气廓线产品概述及下载

MODIS 的 MOD07 大气廓线产品概述及下载

WW、forever的博客 550

单源最短路径(Dijkstra算法详解&&Java实现)

在寻找加权无向图中的最小生成树的Prim算法:构造最小生成树每一步都向这棵树中添加一条新的边。Dijkstra算法采用了类似的方法计算最短路径树。关于Prim算法可点击下方链接进行了解。

一条漂流鱼 1700

DRM遇到的实际问题及领悟(3)

DRM遇到的实际问题及领悟(3)

phmatthaus的专栏 636

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Dijkstra算法详解

Dijkstra算法详解

qq_52905520的博客 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Dijkstra(Java)

从一开始先确定一个最短路径,然后不断去更新该路径,最终得到起始节点到其余节点的最短路径。

wwb623的博客 750

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java实现之迪杰斯特拉(Dijkstra)算法

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

qq_64580912的博客 2448

迪杰斯特拉(Dijkstra)算法java

迪杰斯特拉(Dijkstra)算法java介绍及简单实现

Groot-lin的博客 531

Dijkstra算法详解(附代码)

1、从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径。

tecoes的博客 2629
上一篇: 并查集解析及Java代码实现(附图)
下一篇: 单源最短路径SSSP之Bellman-Ford算法
SpringRolls
博客等级 码龄9年 73粉丝 129原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值