2021-11-25【数据结构/严蔚敏】【Dijkstra】【代码实现算法7.15】
知识点
单源最短路径:Dijkstra
Dikstra算法也用来解决单源最短路径问题。Dijkstra是非常高效而且稳定的算法。
Bellman-Ford算法,提到它在现实中的模型是找警察问路。在现实中 Dijkstra有另外的模型,例如多米诺骨牌,可以想象下面的场景:
在图中所有的边上排满多米诺骨牌,相当于把骨牌看成图的边。一条边上的多米诺骨牌数量和边的权值(例如长度或费用)成正比,规定所有骨牌倒下的速度都是一样的。如果在一个结点上推倒骨牌,会导致这个结点上的所有骨牌都往后面倒下去。
在起点 sss 推倒骨牌,可以观察到,从 sss 开始。它连接的边上的骨牌都逐渐倒下,并到达所有能达到的结点。在某个结点 ttt ,可能先后从不同的线路倒骨牌过来;先倒过来的骨牌,其经过的路径肯定就是从 sss 到达 ttt 的最短路径;后倒过来的骨牌,对确定结点 ttt 的最短路径没有贡献,不用管它。
从整体看,这就是一个从起点;扩散到整个图的过程。在这个过程中观察所有结点的最短路径是这样得到的:
- 在 sss 的所有直连邻居中,最近的邻居 uuu ,骨牌首先到达。 uuu 是第一个确定最短路径的结点。从 uuu 直连到 sss 的路径肯定是最短的,因为如果 uuu 绕道别的结点到 sss ,必然更远。
- 然后,把后面骨牌的倒下分成两个部分,一部分是从 sss 继续例下到 sss 的其他的直连邻居,另一部分是从 uuu 出发倒下到 uuu 的直连邻居。那么下一个到达的结点 vvv 必然是 sss 或者 uuu 的一个直连邻居。 vvv 是第二个确定最短路径的结点。
- 继续以上步骤,在每一次迭代过程中都能确定一个结点的最短路径。
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】相关推荐
- 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...
1.运行环境 这里说明一下这里所有的C语言代码都是基于code::blocks 20.03编译运行的.当然一些其他集成开发环境应该也是可以的,个人不太喜欢功能太过强大的IDE,因为那同样意味着相关设置 ...
- 数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码
数据结构严蔚敏C语言版-线性表顺序存储结构(顺序表)C语言实现相关代码 1.运行环境 2.准备工作 1)项目构建 1>新建一个SeqList项目 2>新建两个文件Sources和Heade ...
- 【计算机】数据结构-严蔚敏/清华大学P3
[计算机]数据结构-严蔚敏/清华大学P1 第二章 线 性表 线性结构 是 一个数据元素的有序(次序)集 线性结构的基本特征: 1. 集合中必存在唯一的一个"第一元素": ...
- 读论文——Pre-Training with Whole Word Masking for Chinese BERT(2021 11.25)
第一遍 标题以及作者(2021 11.25) 摘要 本文基于BERT,在RoBERTa上进行一系列改进,提出了用于中文的预训练模型MacBERT. 提出了一种新的掩码策略,MLM as correct ...
- 数据结构 严蔚敏 第二章 线性表
数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...
- 数据结构严蔚敏清华大学pdf_2019年清华大学自动化系控制工程专业大数据方向考研经验分享...
基本情况(以下内容仅代表个人观点) 我目前就读于西南某双非石油工程专业,2019考研报考清华大学自动化系大数据工程专业,一志愿复试被刷,侥幸调剂录取至微电子系.初试总分346分(政治-63 + 英语一 ...
- 数据结构----严蔚敏
最近一直想找一本纯数据结构的书来学习,找来找去都没有找到一本合适的书籍,相比之下国内的书籍之中,严蔚敏和吴伟民的还算是经典版了,很多国内其他数据结构教材都参考这本书的.但缺点是很多都是伪代码,对编程初 ...
- 史上最详细微信小程序授权登录与后端SprIngBoot交互操作说明,附源代码,有疑惑大家可以直接留言,蟹蟹 2021.11.29完善更新小程序代码,
2021.11.29 更新文章 你好,我是博主宁在春,一起学习吧!!! 写这篇文章的原因,主要是因为最近在写毕业设计,用到了小程序,这中间曲曲折折,一言难尽啊.毕业设计真的让人麻脑阔
- 数据结构 c语言(严蔚敏) 总结 + 代码
第一章 基本绪论 基本概念和术语 数据(Data):客观事物的符号表示,所有能够输入计算中并被计算机处理的符号的总称. 数据元素(Data Element):数据的基本单位,在计算机中作为一个整体进行 ...
- 数据结构严蔚敏代码合集 严书数据结构代码实现 可直接运行 持续更新by myself
建议收藏关注,与严书代码高度一致且可实现运行. 有没更新的或者希望快点的可以催更哦. 版权声明:本文为CSDN博主「七灵微」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本 ...
最新文章
- Xcode 7中http通信出现如下错误
- 6/7 SELECT语句:过滤(正则表达式REGEXP)
- Tomcat10 端口修改 Linux 环境
- 使用双栈实现一个队列
- spring中事务失效的几种情况
- jsp九大内置对象和四种属性范围介绍
- as的Enter_Frame与Timer
- 橘子皮巧治咳嗽痰多 泡茶喝-转
- Excel - 添加趋势线,显示趋势线公式 - 进行行业投融资曲线拟合
- c语言延时跑马灯实验报告,跑马灯实验C语言程序
- 有替代CV520国产非接触式读写器读卡芯片CI520
- windows 设置目录不可执行程序
- 计算机网络监控技术,实现网络流量监控的核心技术要求
- stm32F103R6之BKP(备份寄存器)
- 抖音不搞「盲目」社交
- imac起死回生,在iMAC 27 2011 mid 上裸机安装windows10
- 字符数组与字符串处理函数
- Python函数参数之*与**用法详解
- 安全L1-1.2 信息安全概述-协议层脆弱性分析01-物理层及链路层
- 新技能get,微信提现这样操作可免手续费
热门文章
- Tomcat配置https 访问http跳转https 配置域名
- NW集成打包 自定义图标及注意事项
- 【论文随笔5】Context-Aware Transformer Transducer for Speech Recognition
- 怎么写加密邮件,企业邮箱支持吗?【企业邮箱注册】
- 【R语言】如何进行英文分词统计(以《爱丽丝漫游奇境》词频统计为例)(20年3月22日复习笔记)
- 编出个区块链:数据结构的序列化,看看数字货币如何传输数据
- 双机热备系统的方案与软件浅析
- ios应用中调用系统电话、浏览器、地图、邮件等 以及打开其他应用(如qq,msn)
- 全国大学生电子设计竞赛(三)--线性电源设计
- [2017湖南集训7-8]暗牧 虚树+最短路