知识点

单源最短路径:Dijkstra

Dikstra算法也用来解决单源最短路径问题。Dijkstra是非常高效而且稳定的算法。

Bellman-Ford算法,提到它在现实中的模型是找警察问路。在现实中 Dijkstra有另外的模型,例如多米诺骨牌,可以想象下面的场景:

在图中所有的边上排满多米诺骨牌,相当于把骨牌看成图的边。一条边上的多米诺骨牌数量和边的权值(例如长度或费用)成正比,规定所有骨牌倒下的速度都是一样的。如果在一个结点上推倒骨牌,会导致这个结点上的所有骨牌都往后面倒下去。

在起点 sss 推倒骨牌,可以观察到,从 sss 开始。它连接的边上的骨牌都逐渐倒下,并到达所有能达到的结点。在某个结点 ttt ,可能先后从不同的线路倒骨牌过来;先倒过来的骨牌,其经过的路径肯定就是从 sss 到达 ttt 的最短路径;后倒过来的骨牌,对确定结点 ttt 的最短路径没有贡献,不用管它

从整体看,这就是一个从起点;扩散到整个图的过程。在这个过程中观察所有结点的最短路径是这样得到的:

  1. 在 sss 的所有直连邻居中,最近的邻居 uuu ,骨牌首先到达。 uuu 是第一个确定最短路径的结点。从 uuu 直连到 sss 的路径肯定是最短的,因为如果 uuu 绕道别的结点到 sss ,必然更远。
  2. 然后,把后面骨牌的倒下分成两个部分,一部分是从 sss 继续例下到 sss 的其他的直连邻居,另一部分是从 uuu 出发倒下到 uuu 的直连邻居。那么下一个到达的结点 vvv 必然是 sss 或者 uuu 的一个直连邻居。 vvv 是第二个确定最短路径的结点。
  3. 继续以上步骤,在每一次迭代过程中都能确定一个结点的最短路径。

Dijkstra算法应用了贪心法的思想,即“抄近路走",肯定能找到最短路径。

在上述步骤中可以发现:Dijkstra的每次选代,只需要检查上次已经确定最短路径的那些结点的邻居,检查范围很小,算法是高效的;每次迭代,都能得到至少一个结点的最短路径,算法是稳定的。

与Bellman Ford 对比:

Bellman-Ford 是分布式的思想;面 Dijkstra必须从起点s开始扩散和计算,是集中式的思想。读者可以试试在多米诺骨牌模型中运用Bellman-Ford,看看行不行。

算法实现


//算法7.15
void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D){
/*  用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度 D[v]。若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。 final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径 算法7.15 */int v, w, i, j, min;Status final[MAX_VERTEX_NUM];for (v = 0; v < G.vexnum; ++v){final[v] = FALSE;D[v] = G.arcs[v0][v].adj;for (w = 0; w < G.vexnum; ++w)P[v][w] = FALSE; if (D[v] < INFINITY){P[v][v0] = TRUE;P[v][v] = TRUE;}}D[v0] = 0;final[v0] = TRUE;               // 初始化,v0顶点属于S集 for (i = 1; i < G.vexnum; ++i)    //其余G.vexnum-1个顶点 {                                 // 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 min = INFINITY;                      // 当前所知离v0顶点的最近距离 for (w = 0; w < G.vexnum; ++w)if (!final[w])                        // w顶点在V-S中 if (D[w] < min){v = w;min = D[w];}                                 //w顶点离v0顶点更近 final[v] = TRUE;                      // 离v0顶点最近的v加入S集 for (w = 0; w < G.vexnum; ++w) {     // 更新当前最短路径及距离 if (!final[w] && min < INFINITY&&G.arcs[v][w].adj < INFINITY && (min + G.arcs[v][w].adj < D[w])){D[w] = min + G.arcs[v][w].adj;for (j = 0; j < G.vexnum; ++j)P[w][j] = P[v][j];P[w][w] = TRUE;}}}
}

完整代码

#include<bits/stdc++.h>
using namespace std;/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int Boolean;
#define MAX_NAME 5
#define MAX_INFO 20
typedef int VRType;
typedef char InfoType;
typedef char VertexType[MAX_NAME];/* ------------------  图的数组(邻接矩阵)存储表示    ----------------*/
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
typedef enum { DG, DN, AG, AN }GraphKind;
typedef struct{VRType adj; InfoType *info;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{VertexType vexs[MAX_VERTEX_NUM];AdjMatrix arcs; int vexnum, arcnum; GraphKind kind;
}MGraph;typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef int ShortPathTable[MAX_VERTEX_NUM];/* -----------  需要用的图的数组(邻接矩阵)存储的基本操作 -----------*/int LocateVex(MGraph G, VertexType u){
/*  初始条件:图G存在,u和G中顶点有相同特征 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */int i;for (i = 0; i < G.vexnum; ++i)if (strcmp(u, G.vexs[i]) == 0)return i;return -1;
}Status CreateDN(MGraph &G){int i, j, k, w, IncInfo;char s[MAX_INFO], *info;VertexType va, vb;printf("请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0)(以空格作为间隔): ");scanf("%d%d%d", &G.vexnum, &G.arcnum, &IncInfo);printf("请输入%d个顶点的值(<%d个字符):\n", G.vexnum, MAX_NAME);for (i = 0; i < G.vexnum; ++i) scanf("%s", G.vexs[i]);for (i = 0; i < G.vexnum; ++i) for (j = 0; j < G.vexnum; ++j){G.arcs[i][j].adj = INFINITY; G.arcs[i][j].info = NULL;}printf("请输入%d条弧的弧尾 弧头 权值(以空格作为间隔): \n", G.arcnum);for (k = 0; k < G.arcnum; ++k){scanf("%s%s%d%*c", va, vb, &w);  i = LocateVex(G, va);j = LocateVex(G, vb);G.arcs[i][j].adj = w;if (IncInfo){printf("请输入该弧的相关信息(<%d个字符): ", MAX_INFO);gets(s);w = strlen(s);if (w){info = (char*)malloc((w + 1) * sizeof(char));strcpy(info, s);G.arcs[i][j].info = info; }}}G.kind = DN;return OK;
}//算法7.15
void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D){
/*  用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度 D[v]。若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。 final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径 算法7.15 */int v, w, i, j, min;Status final[MAX_VERTEX_NUM];for (v = 0; v < G.vexnum; ++v){final[v] = FALSE;D[v] = G.arcs[v0][v].adj;for (w = 0; w < G.vexnum; ++w)P[v][w] = FALSE; if (D[v] < INFINITY){P[v][v0] = TRUE;P[v][v] = TRUE;}}D[v0] = 0;final[v0] = TRUE;               // 初始化,v0顶点属于S集 for (i = 1; i < G.vexnum; ++i)    //其余G.vexnum-1个顶点 {                                 // 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集 min = INFINITY;                      // 当前所知离v0顶点的最近距离 for (w = 0; w < G.vexnum; ++w)if (!final[w])                        // w顶点在V-S中 if (D[w] < min){v = w;min = D[w];}                                 //w顶点离v0顶点更近 final[v] = TRUE;                      // 离v0顶点最近的v加入S集 for (w = 0; w < G.vexnum; ++w) {     // 更新当前最短路径及距离 if (!final[w] && min < INFINITY&&G.arcs[v][w].adj < INFINITY && (min + G.arcs[v][w].adj < D[w])){D[w] = min + G.arcs[v][w].adj;for (j = 0; j < G.vexnum; ++j)P[w][j] = P[v][j];P[w][w] = TRUE;}}}
}int main(){int i, j, v0 = 0; MGraph g;PathMatrix p;ShortPathTable d;CreateDN(g);ShortestPath_DIJ(g, v0, p, d);printf("最短路径数组 PathMatrix[i][j] 如下:\n");for (i = 0; i < g.vexnum; ++i){for (j = 0; j < g.vexnum; ++j)printf("%2d", p[i][j]);printf("\n");}printf("%s到各顶点的最短路径长度为:\n", g.vexs[0]);for (i = 1; i < g.vexnum; ++i)printf("%s-%s:%d\n", g.vexs[0], g.vexs[i], d[i]);return 0;
}

测试样例

请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0)(以空格作为间隔): 6 8 0
请输入6个顶点的值(<5个字符):
v0 v1 v2 v3 v4 v5
请输入8条弧的弧尾 弧头 权值(以空格作为间隔):
v0 v5 100
v0 v4 30
v0 v2 10
v1 v2 5
v2 v3 50
v3 v5 10
v4 v3 20
v4 v5 60

运行结果

最短路径数组 PathMatrix[i][j] 如下:0 0 0 0 0 00 0 0 0 0 01 0 1 0 0 01 0 0 1 1 01 0 0 0 1 01 0 0 1 1 1
v0到各顶点的最短路径长度为:
v0-v1:2147483647
v0-v2:10
v0-v3:50
v0-v4:30
v0-v5:60

更多数据结构代码实现请关注我的专栏数据结构

或者进入2021-10-16【严蔚敏数据结构代码实现合集】【c语言学习必备】学习

2021-11-25【数据结构/严蔚敏】【Dijkstra】【代码实现算法7.15】相关推荐

  1. 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...

    1.运行环境 这里说明一下这里所有的C语言代码都是基于code::blocks 20.03编译运行的.当然一些其他集成开发环境应该也是可以的,个人不太喜欢功能太过强大的IDE,因为那同样意味着相关设置 ...

  2. 数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码

    数据结构严蔚敏C语言版-线性表顺序存储结构(顺序表)C语言实现相关代码 1.运行环境 2.准备工作 1)项目构建 1>新建一个SeqList项目 2>新建两个文件Sources和Heade ...

  3. 【计算机】数据结构-严蔚敏/清华大学P3

    [计算机]数据结构-严蔚敏/清华大学P1 第二章    线  性表 线性结构 是 一个数据元素的有序(次序)集 线性结构的基本特征: 1.  集合中必存在唯一的一个"第一元素": ...

  4. 读论文——Pre-Training with Whole Word Masking for Chinese BERT(2021 11.25)

    第一遍 标题以及作者(2021 11.25) 摘要 本文基于BERT,在RoBERTa上进行一系列改进,提出了用于中文的预训练模型MacBERT. 提出了一种新的掩码策略,MLM as correct ...

  5. 数据结构 严蔚敏 第二章 线性表

    数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...

  6. 数据结构严蔚敏清华大学pdf_2019年清华大学自动化系控制工程专业大数据方向考研经验分享...

    基本情况(以下内容仅代表个人观点) 我目前就读于西南某双非石油工程专业,2019考研报考清华大学自动化系大数据工程专业,一志愿复试被刷,侥幸调剂录取至微电子系.初试总分346分(政治-63 + 英语一 ...

  7. 数据结构----严蔚敏

    最近一直想找一本纯数据结构的书来学习,找来找去都没有找到一本合适的书籍,相比之下国内的书籍之中,严蔚敏和吴伟民的还算是经典版了,很多国内其他数据结构教材都参考这本书的.但缺点是很多都是伪代码,对编程初 ...

  8. 史上最详细微信小程序授权登录与后端SprIngBoot交互操作说明,附源代码,有疑惑大家可以直接留言,蟹蟹 2021.11.29完善更新小程序代码,

    2021.11.29 更新文章 你好,我是博主宁在春,一起学习吧!!! 写这篇文章的原因,主要是因为最近在写毕业设计,用到了小程序,这中间曲曲折折,一言难尽啊.毕业设计真的让人麻脑阔

  9. 数据结构 c语言(严蔚敏) 总结 + 代码

    第一章 基本绪论 基本概念和术语 数据(Data):客观事物的符号表示,所有能够输入计算中并被计算机处理的符号的总称. 数据元素(Data Element):数据的基本单位,在计算机中作为一个整体进行 ...

  10. 数据结构严蔚敏代码合集 严书数据结构代码实现 可直接运行 持续更新by myself

    建议收藏关注,与严书代码高度一致且可实现运行. 有没更新的或者希望快点的可以催更哦. 版权声明:本文为CSDN博主「七灵微」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本 ...

最新文章

  1. Xcode 7中http通信出现如下错误
  2. 6/7 SELECT语句:过滤(正则表达式REGEXP)
  3. Tomcat10 端口修改 Linux 环境
  4. 使用双栈实现一个队列
  5. spring中事务失效的几种情况
  6. jsp九大内置对象和四种属性范围介绍
  7. as的Enter_Frame与Timer
  8. 橘子皮巧治咳嗽痰多 泡茶喝-转
  9. Excel - 添加趋势线,显示趋势线公式 - 进行行业投融资曲线拟合
  10. c语言延时跑马灯实验报告,跑马灯实验C语言程序
  11. 有替代CV520国产非接触式读写器读卡芯片CI520
  12. windows 设置目录不可执行程序
  13. 计算机网络监控技术,实现网络流量监控的核心技术要求
  14. stm32F103R6之BKP(备份寄存器)
  15. 抖音不搞「盲目」社交
  16. imac起死回生,在iMAC 27 2011 mid 上裸机安装windows10
  17. 字符数组与字符串处理函数
  18. Python函数参数之*与**用法详解
  19. 安全L1-1.2 信息安全概述-协议层脆弱性分析01-物理层及链路层
  20. 新技能get,微信提现这样操作可免手续费

热门文章

  1. Tomcat配置https 访问http跳转https 配置域名
  2. NW集成打包 自定义图标及注意事项
  3. 【论文随笔5】Context-Aware Transformer Transducer for Speech Recognition
  4. 怎么写加密邮件,企业邮箱支持吗?【企业邮箱注册】
  5. 【R语言】如何进行英文分词统计(以《爱丽丝漫游奇境》词频统计为例)(20年3月22日复习笔记)
  6. 编出个区块链:数据结构的序列化,看看数字货币如何传输数据
  7. 双机热备系统的方案与软件浅析
  8. ios应用中调用系统电话、浏览器、地图、邮件等 以及打开其他应用(如qq,msn)
  9. 全国大学生电子设计竞赛(三)--线性电源设计
  10. [2017湖南集训7-8]暗牧 虚树+最短路