Dijkstra算法解析

news2025/2/3 22:12:02

Dijkstra算法,用于求解图中从一个起点到其他所有节点的最短路径。解决单源最短路径问题的有效方法。

条件

有向

带权路径

时间复杂度 O(n平方)

方法步骤

1 把图上的点分为两个集合 要求的起点 和除了起点之外的点 。能直达的写上权值 不能直达的写上无穷 自己到自己的距离是0

2 在除起点以外的中找权值最小的顶点,这个顶点加入起点所在的集合。由于新顶点的并入,可以把新顶点作为中转点,再重新计算起点到所有除已经并入顶点的距离,找最小的继续并入,直到所有顶点并入起点所在的集合。

以下是对代码的详细解析和注释:

代码解析

全局变量定义
#define N 1005 // 定义最大顶点数为1005
int n, m; // n表示顶点数,m表示边数
bool str[N]; // 用于标记是否已确定最短路径
int dis[N]; // 存储从起始点到各个顶点的最短距离
int g[N][N]; // 邻接矩阵,存储图的结构
  • N:定义图中最大顶点数为1005。

  • nm:分别表示图中的顶点数和边数。

  • str:布尔数组,用于标记某个顶点是否已经确定了最短路径。

  • dis:数组,存储从起点到每个顶点的最短距离。

  • g:邻接矩阵,g[i][j] 表示从顶点 i 到顶点 j 的距离。

Dijkstra算法实现
void dijkstra() {
    // 初始化dis数组为一个很大的值(这里选择0x3f3f3f3f)
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    
    // 起始点到自身的距离为0
    dis[1] = 0;
    
    for (int i = 1; i <= n; ++i) {
        int temp = -1; // 选择未确定的顶点
        
        // 寻找当前未确定的最小距离顶点
        for (int j = 1; j <= n; ++j)
            if (!str[j] && (temp == -1 || dis[j] < dis[temp]))
                temp = j;
        
        // 更新与该顶点相邻的其他顶点的距离
        for (int j = 1; j <= n; ++j)
            dis[j] = min(dis[j], dis[temp] + g[temp][j]);
        
        // 标记该顶点已经确定了最短路径
        str[temp] = true;
    }
    
    // 输出结果
    for (int i = 1; i <= n; ++i) {
        if (dis[i] == 0x3f3f3f3f)
            cout << "-1" << " "; // 如果没有到该顶点的路径则输出-1
        else
            cout << dis[i] << " "; // 否则输出最短距离
    }
}
  1. 初始化

    • memset(dis, 0x3f3f3f3f, sizeof(dis));:将 dis 数组初始化为一个很大的值(0x3f3f3f3f),表示初始时从起点到其他顶点的距离是无穷大。

    • dis[1] = 0;:将起点到自身的距离设置为0。

  2. 主循环

    • for (int i = 1; i <= n; ++i):循环 n 次,每次找到一个未确定最短路径的顶点。

    • int temp = -1;:初始化当前未确定的最短距离顶点为 -1。

    • for (int j = 1; j <= n; ++j):遍历所有顶点,找到未确定最短路径的顶点中距离最短的顶点 temp

      • if (!str[j] && (temp == -1 || dis[j] < dis[temp])):如果顶点 j 未确定最短路径且距离更短,则更新 temp

    • for (int j = 1; j <= n; ++j):更新与顶点 temp 相邻的其他顶点的距离。

      • dis[j] = min(dis[j], dis[temp] + g[temp][j]);:如果通过 temp 到达 j 的距离更短,则更新 dis[j]

    • str[temp] = true;:标记顶点 temp 已经确定了最短路径。

  3. 结果输出

    • 遍历 dis 数组,输出从起点到每个顶点的最短距离。

    • 如果 dis[i] 仍然是 0x3f3f3f3f,表示没有路径到达顶点 i,输出 -1

    • 否则输出 dis[i]

主函数
int main() {
    // 初始化邻接矩阵g为一个很大的值
    memset(g, 0x3f3f3f3f, sizeof(g));
    
    // 输入顶点数n和边数m
    cin >> n >> m;
    
    while (m--) { // 处理每一条边的输入
        int x, y, z;
        cin >> x >> y >> z;
        // 更新邻接矩阵g中的权值
        g[x][y] = min(g[x][y], z);
    }
    
    // 调用dijkstra函数求解
    dijkstra();
    
    return 0;
}
  1. 初始化邻接矩阵

    • memset(g, 0x3f3f3f3f, sizeof(g));:将邻接矩阵 g 初始化为一个很大的值(0x3f3f3f3f),表示初始时图中没有边。

  2. 输入图的边

    • cin >> n >> m;:读取顶点数 n 和边数 m

    • while (m--):循环 m 次,读取每一条边的信息。

      • cin >> x >> y >> z;:读取边的起点 x、终点 y 和权重 z

      • g[x][y] = min(g[x][y], z);:更新邻接矩阵 g 中的权值,如果有多条边连接同一对顶点,只保留权重最小的那条边。

  3. 调用Dijkstra算法

    • dijkstra();:调用 dijkstra 函数求解最短路径。

  4. 输出结果

    • dijkstra 函数会输出从起点到每个顶点的最短距离。

示例输入和输出

示例输入
5 7
1 2 4
1 3 3
2 4 2
3 2 1
3 4 5
4 5 1
2 5 7
示例输出

0 2 3 4 5

解释
  • 顶点 1 到顶点 2 的最短距离为 2(1 -> 3 -> 2)。

  • 顶点 1 到顶点 3 的最短距离为 3(1 -> 3)。

  • 顶点 1 到顶点 4 的最短距离为 4(1 -> 3 -> 2 -> 4)。

  • 顶点 1 到顶点 5 的最短距离为 5(1 -> 3 -> 2 -> 4 -> 5)。

关键点总结

  1. 邻接矩阵:使用二维数组 g[N][N] 表示图的结构,g[i][j] 表示从顶点 i 到顶点 j 的距离。

  2. 选择最短距离顶点:通过遍历所有顶点,找到未确定最短路径的顶点中距离最短的顶点。

  3. 更新邻接顶点的距离:通过当前顶点更新其邻接顶点的距离。

  4. 标记顶点:使用布尔数组 str 标记顶点是否已经确定了最短路径。

Dijkstra算法详细步骤解析

1. 初始化

在算法开始之前,需要进行以下初始化操作:

  1. 初始化距离数组 dis

    • dis 数组中的所有元素初始化为一个很大的值(如 0x3f3f3f3f),表示从起点到其他顶点的距离初始为无穷大。

    • 将起点的距离设置为 0,即 dis[start] = 0

  2. 初始化访问标记数组 str

    • str 数组中的所有元素初始化为 false,表示所有顶点初始时都未被访问过。

  3. 初始化邻接矩阵 g

    • 将邻接矩阵 g 中的所有元素初始化为一个很大的值(如 0x3f3f3f3f),表示初始时图中没有边。

2. 主循环

Dijkstra算法的核心是一个主循环,该循环执行 n 次(n 为顶点数),每次找到一个未访问的最短距离顶点,并更新其邻接顶点的距离。

  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u

    • 如果所有顶点都已被访问过,或者没有找到未访问的顶点,则退出循环。

  2. 更新邻接顶点的距离

    • 遍历顶点 u 的所有邻接顶点 v,如果通过 u 到达 v 的距离更短,则更新 dis[v]

    • 具体来说,如果 dis[u] + g[u][v] < dis[v],则更新 dis[v] = dis[u] + g[u][v]

  3. 标记顶点为已访问

    • 将顶点 u 标记为已访问,即 str[u] = true,避免重复处理。

3. 结果输出

在主循环结束后,dis 数组中存储了从起点到每个顶点的最短距离。遍历 dis 数组,输出结果:

  • 如果 dis[i] 仍然是初始的大值(如 0x3f3f3f3f),表示没有路径到达顶点 i,输出 -1

  • 否则,输出 dis[i],表示从起点到顶点 i 的最短距离。

示例执行过程

假设图的结构如下:

  • 顶点数 n = 5

  • 边数 m = 7

  • 边的权重如下:

    • 1 -> 2: 4

    • 1 -> 3: 3

    • 2 -> 4: 2

    • 3 -> 2: 1

    • 3 -> 4: 5

    • 4 -> 5: 1

    • 2 -> 5: 7

初始化
  • dis 数组:[0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f]

  • str 数组:[false, false, false, false, false]

  • g 邻接矩阵:

    [
      [0x3f3f3f3f, 4, 3, 0x3f3f3f3f, 0x3f3f3f3f],
      [0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 2, 0x3f3f3f3f],
      [0x3f3f3f3f, 1, 0x3f3f3f3f, 5, 0x3f3f3f3f],
      [0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 1],
      [0x3f3f3f3f, 7, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f]
    ]
第1次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 1(起点)。

  2. 更新邻接顶点的距离

    • 遍历顶点 1 的邻接顶点 23

      • dis[2] = min(dis[2], dis[1] + g[1][2]) = min(0x3f3f3f3f, 0 + 4) = 4

      • dis[3] = min(dis[3], dis[1] + g[1][3]) = min(0x3f3f3f3f, 0 + 3) = 3

  3. 标记顶点为已访问

    • str[1] = true

第2次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 3dis[3] = 3)。

  2. 更新邻接顶点的距离

    • 遍历顶点 3 的邻接顶点 24

      • dis[2] = min(dis[2], dis[3] + g[3][2]) = min(4, 3 + 1) = 4

      • dis[4] = min(dis[4], dis[3] + g[3][4]) = min(0x3f3f3f3f, 3 + 5) = 8

  3. 标记顶点为已访问

    • str[3] = true

第3次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 2dis[2] = 4)。

  2. 更新邻接顶点的距离

    • 遍历顶点 2 的邻接顶点 45

      • dis[4] = min(dis[4], dis[2] + g[2][4]) = min(8, 4 + 2) = 6

      • dis[5] = min(dis[5], dis[2] + g[2][5]) = min(0x3f3f3f3f, 4 + 7) = 11

  3. 标记顶点为已访问

    • str[2] = true

第4次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 4dis[4] = 6)。

  2. 更新邻接顶点的距离

    • 遍历顶点 4 的邻接顶点 5

      • dis[5] = min(dis[5], dis[4] + g[4][5]) = min(11, 6 + 1) = 7

  3. 标记顶点为已访问

    • str[4] = true

第5次循环
  1. 选择未访问的最短距离顶点

    • 遍历所有顶点,找到未访问的顶点中距离最短的顶点 u = 5dis[5] = 7)。

  2. 更新邻接顶点的距离

    • 顶点 5 没有邻接顶点,无需更新。

  3. 标记顶点为已访问

    • str[5] = true

结果输出

遍历 dis 数组,输出从起点到每个顶点的最短距离:

  • dis[1] = 0

  • dis[2] = 4

  • dis[3] = 3

  • dis[4] = 6

  • dis[5] = 7

关键点总结

  1. 选择未访问的最短距离顶点

    • 每次选择未访问的顶点中距离最短的顶点,确保每一步都选择当前最优的顶点进行处理。

  2. 更新邻接顶点的距离

    • 通过当前顶点更新其邻接顶点的距离,确保每一步都更新到最新的最短距离。

  3. 标记顶点为已访问

    • 避免重复处理已访问的顶点,提高算法的效率。

  4. 结果输出

    • 最终输出从起点到每个顶点的最短距离,如果没有路径到达某个顶点,则输出 -1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2291469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习深度解析:从基础到前沿

引言 深度学习作为人工智能的一个重要分支&#xff0c;通过模拟人脑的神经网络结构来进行数据分析和模式识别。它在图像识别、自然语言处理、语音识别等领域取得了显著成果。本文将深入探讨深度学习的基础知识、主要模型架构以及当前的研究热点和发展趋势。 基础概念与数学原理…

如何使用SliverGrid组件

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了SliverList组件相关的内容&#xff0c;本章回中将介绍SliverGrid组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的SliverGrid组件是一种网格类组件&#xff0c;主要用来…

K8S集群架构及主机准备

本次集群部署主机分布K8S集群主机配置主机静态IP设置主机名解析ipvs管理工具安装及模块加载主机系统升级主机间免密登录配置主机基础配置完后最好做个快照备份 2台负载均衡器 Haproxy高可用keepalived3台k8s master节点5台工作节点(至少2及以上)本次集群部署主机分布 K8S集群主…

012-51单片机CLD1602显示万年历+闹钟+农历+整点报时

1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台&#xff0c;可以根据需要自行焊接模块&#xff0c;这是用立创EDA画的一个双层PCB板&#xff0c;所以模块都是插针式&#xff0c;不是表贴的。电路原理图在文末的链接里&#xff0c;PCB图暂时不选择开源。 B站上传的…

数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)

一、数据集 二、导入数据 三、K-Means聚类 数据说明:提供一组数据,含体重、胆固醇、性别。 分析目标:找到这组数据中需要治疗的群体供后续使用。 一、数据集 点击下载数据集 二、导入数据 三、K-Means聚类 Ending, congratulations, youre done.

深度学习查漏补缺:1.梯度消失、梯度爆炸和残差块

一、梯度消失 梯度消失的根本原因在于 激活函数的性质和链式法则的计算&#xff1a; 激活函数的导数很小&#xff1a; 常见的激活函数&#xff08;例如 Sigmoid 和 Tanh&#xff09;在输入较大或较小时&#xff0c;输出趋于饱和&#xff08;Sigmoid 的输出趋于 0 或 1&#xf…

于动态规划的启幕之章,借 C++ 笔触绘就算法新篇

注意&#xff1a;代码由易到难 P1216 [IOI 1994] 数字三角形 Number Triangles 题目链接&#xff1a;[IOI 1994] 数字三角形 Number Triangles - 洛谷 题目描述 观察下面的数字金字塔。 写一个程序来查找从最高点到底部任意处结束的路径&#xff0c;使路径经过数字的和最大。每…

基于开源2 + 1链动模式AI智能名片S2B2C商城小程序的内容创作与传播效能探究

摘要&#xff1a;本文围绕开源2 1链动模式AI智能名片S2B2C商城小程序&#xff0c;深入探讨在其应用场景下内容创作与传播效果的关键要素——转发数与转化率。通过剖析如何创作引发用户共鸣、提升用户信任的内容&#xff0c;阐明深度思考内容本质对于实现有效传播的重要性&…

深度学习之“线性代数”

线性代数在深度学习中是解决多维数学对象计算问题的核心工具。这些数学对象包括标量、向量、矩阵和张量&#xff0c;借助它们可以高效地对数据进行操作和建模。以下将详细介绍这些数学对象及其在深度学习中的典型用途。 数学对象概述 标量 标量是最简单的数学对象&#xff0…

SpringBoot的配置(配置文件、加载顺序、配置原理)

文章目录 SpringBoot的配置(配置文件、加载顺序、配置原理)一、引言二、配置文件1、配置文件的类型1.1、配置文件的使用 2、多环境配置 三、加载顺序四、配置原理五、使用示例1、配置文件2、配置类3、控制器 六、总结 SpringBoot的配置(配置文件、加载顺序、配置原理) 一、引言…

CVE-2023-38831 漏洞复现:win10 压缩包挂马攻击剖析

目录 前言 漏洞介绍 漏洞原理 产生条件 影响范围 防御措施 复现步骤 环境准备 具体操作 前言 在网络安全这片没有硝烟的战场上&#xff0c;新型漏洞如同隐匿的暗箭&#xff0c;时刻威胁着我们的数字生活。其中&#xff0c;CVE - 2023 - 38831 这个关联 Win10 压缩包挂…

Clion开发STM32时使用stlink下载程序与Debug调试

一、下载程序 先创建一个文件夹&#xff1a; 命名&#xff1a;stlink.cfg 写入以下代码: # choose st-link/j-link/dap-link etc. #adapter driver cmsis-dap #transport select swdsource [find interface/stlink.cfg]transport select hla_swdsource [find target/stm32f4x.…

无人机图传模块 wfb-ng openipc-fpv,4G

openipc 的定位是为各种模块提供底层的驱动和linux最小系统&#xff0c;openipc 是采用buildroot系统编译而成&#xff0c;因此二次开发能力有点麻烦。为啥openipc 会用于无人机图传呢&#xff1f;因为openipc可以将现有的网络摄像头ip-camera模块直接利用起来&#xff0c;从而…

C语言 --- 分支

C语言 --- 分支 语句分支语句含义if...else语句单分支if语句语法形式 双分支 if-else 语句语法形式 悬空else含义问题描述 多分支 if-else 语句语法形式 switch...case语句含义语法形式 总结 &#x1f4bb;作者简介&#xff1a;曾与你一样迷茫&#xff0c;现以经验助你入门 C 语…

低代码系统-产品架构案例介绍、炎黄盈动-易鲸云(十二)

易鲸云作为炎黄盈动新推出的产品&#xff0c;在定位上为低零代码产品。 开发层 表单引擎 表单设计器&#xff0c;包括设计和渲染 流程引擎 流程设计&#xff0c;包括设计和渲染&#xff0c;需要说明的是&#xff1a;采用国际标准BPMN2.0&#xff0c;可以全球通用 视图引擎 视图…

自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…

[c语言日寄]C语言类型转换规则详解

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

利用Spring Batch简化企业级批处理应用开发

1. 引言 1.1 批处理的重要性 在现代企业系统中,批处理任务用于处理大量数据,如报表生成、数据迁移、日终结算等。这些任务通常不需要实时响应,但需要高效、可靠地完成。批处理可以显著提高系统性能,减少实时系统的负载,并确保数据的完整性和一致性。 1.2 Spring Batch简…

三、js笔记

(一)JavaScript概述 1、发展历史 ScriptEase.(客户端执行的语言):1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言)Javascript:Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigat…

基于SpringBoot的青年公寓服务平台的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…