最短路径——Dijkstar算法
背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的。该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解。
Dijkstar算法理解:
Dijkstar算法的核心思想就是通过一次一次的迭代,逐个寻找起始顶点到图中每一个顶点的最短路径,并在确定一个顶点的最短路径之后,设置标志位,同时根据最新确定的顶点的最短路径,对其他与之相关顶点的最短路径进行修正和更新。
如图(摘录自小甲鱼教学视频中的图片),是一个带有权值的连通网:

根据上图可以列写出该连通网的邻接矩阵,为了方便直观的理解:
| 权值 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| V0 | 0 | 1 | 5 | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ |
| V1 | 1 | 0 | 3 | 7 | 5 | Ꚙ | Ꚙ | Ꚙ | Ꚙ |
| V2 | 5 | 3 | 0 | Ꚙ | 1 | 7 | Ꚙ | Ꚙ | Ꚙ |
| V3 | Ꚙ | 7 | Ꚙ | 0 | 2 | Ꚙ | 3 | Ꚙ | Ꚙ |
| V4 | Ꚙ | 5 | 1 | 2 | 0 | 3 | 6 | 9 | Ꚙ |
| V5 | Ꚙ | Ꚙ | 7 | Ꚙ | 3 | 0 | Ꚙ | 5 | Ꚙ |
| V6 | Ꚙ | Ꚙ | Ꚙ | 3 | 6 | Ꚙ | 0 | 2 | 7 |
| V7 | Ꚙ | Ꚙ | Ꚙ | Ꚙ | 9 | 5 | 2 | 0 | 4 |
| V8 | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ | 7 | 4 | 0 |
算法流程:(叙述过程中用D数组表示各点最短路径的权值和数组,用P数组表示最短路径的下标数组)
算法流程和最下方的算法代码结合在一起看,方便理解。
1、第一个循环
D数组初始化时幅值为邻接矩阵中V0(起始顶点)行。V0顶点默认已经确定了最短路径。
第一个for循环,首先在未确定最短路径的所有顶点中寻找与V0直接相连,且权值最小的顶点,得到k = 1(k保存前驱顶点);min = 1(min保存到达前驱顶点的最短路径权值和),在这个for循环中,找到的这个顶点可以直接确定找到了最短路径(因为每次在第二个for循环中,都进行了对于其他未确定最短路径的顶点的路径优化)。
第二个for循环对于路径进行优化,优化原则为:如果 【到达前驱顶点的权值和(即min)+ 前驱顶点到达其他未确定最短路径的顶点的权值 < 当前D数组中达到该顶点的权值和 】则说明当前到达该顶点的路径不够优化,此时即可采用经过当前前驱顶点到达那个顶点的路径替换之前的路径,即同时更新P数组,将当前的k中保存的前驱顶点作为那个顶点的前驱。
| D数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=1,min=1 | 0 | 1 | 5 | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ | Ꚙ |
| 优化路径 | 0 | 1 | 4 | 8 | 6 | Ꚙ | Ꚙ | Ꚙ | Ꚙ |
| P数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=1 优化 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
2、第二个循环
相同的原理进行一次迭代,结果如下(注意自己过流程的时候,对照上面的邻接矩阵):
| D数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=2,min=4 | 0 | 1 | 4 | 8 | 6 | Ꚙ | Ꚙ | Ꚙ | Ꚙ |
| 优化路径 | 0 | 1 | 4 | 8 | 5 | 11 | Ꚙ | Ꚙ | Ꚙ |
| P数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=2 优化 | 0 | 0 | 1 | 1 | 2 | 2 | 0 | 0 | 0 |
3、第三个循环
相同的原理进行一次迭代,结果如下:
| D数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=4,min=5 | 0 | 1 | 4 | 8 | 5 | 11 | Ꚙ | Ꚙ | Ꚙ |
| 优化路径 | 0 | 1 | 4 | 7 | 5 | 8 | 11 | 14 | Ꚙ |
| P数组 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| k=4 优化 | 0 | 0 | 1 | 4 | 2 | 4 | 4 | 4 | 0 |
......如此循环n次(n为顶点数),即可已得到最短路径,结果如下:
| 结果 | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 |
| D数组 | 0 | 1 | 4 | 7 | 5 | 8 | 10 | 12 | 16 |
| P数组 | 0 | 0 | 1 | 4 | 2 | 4 | 3 | 6 | 7 |
| final数组 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
根据D数组可以得到从起始点到达任何一个顶点的最短路径权值和,根据P数组可以得到每一个顶点的最短路径中的前驱顶点,进而可以连接生成最短路径,该例题中到达V8的最短路径为:

代码如下:
#define MAXVEX 9
#define INFINITY 65535
/* 用来存储最短路径下标的数组 */
typedef int Patharc[MAXVEX];
/* 用来存储到各点最短路径的权值和 */
typedef int ShortPathTable[MAXVEX];
void ShortestPath_Dijkstar(MGragh G,int V0,Patharc *P,ShortPathTable *D)
{
int v,w,k,min;
/* final[w] = 1表示已经求得顶点Vo到Vw的最短路径 */
int final[MAXVEX];
/* init */
for(v=0;v<G.numVertexes;v++)
{
/* 全部顶点初始化为未找到最短路径 */
final[v] = 0;
/* 起始点V0到其他点之间的最短路径数组赋初始值:即邻接矩阵中V0行的值 */
/* 即到与V0有有直接连线的点的最短路径为边的权值;无直接连线的点的最短路径为最大值 */
(*D)[v] = G.arc[V0][v];
/* 初始化路径数组P为0 */
(*P)[v] = 0;
}
/* V0到V0的路径为0 */
(*D)[V0] = 0;
/* V0到V0不需要求路径 */
final[V0] = 1;
/* 主循环 每次求得V0到某个V顶点的最短路径 */
/* 从v=1开始循环因为v0点的最短路径已经自动赋值为0 */
for(v=1;v<G.numVertexes;v++)
{
min = INFINITY;
/* 第一个for循环 */
for(w=0;w<G.numVertexes;w++)
{
/* 判断final数组(即未求得最短路径) */
/* 仅对未确定最短路径的顶点 在D数组中寻找最小权值 */
/* 因为经过下一个for循环的最短路径修正之后,未确定最短路径的顶点中到V0权值最小的顶点,经过的必然是到该店的最短路径 */
if(!final[w] && (*D)[w]<min)
{
/* k暂时保存前驱顶点 */
k = w;
/* min暂时保存到达前驱顶点的最短路径权值和 */
min = (*D)[w];
}
}
/* 标志当前顶点以找到了最短路径 */
final[k] = 1;
/* 在找到拥有最短路径的最新的一个顶点后,修正最短路径及距离 */
/* 原先可能某些未确定最短路径的顶点,选择的路径不够优化(以此顶点的最优路径对其进行优化) */
/* 第二个for循环 */
for(w=0;w<G.numVertexes;w++)
{
/* 前驱顶点已经确认为最短路径(即min) */
/* 如果经过之前保存的前驱顶点的路径比现在这条路径(D数组中原本的)的长度短的话 更新更优的路径 */
if(!final[w] && (min+G.arc[k][w]<(*D)[w]))
{
/* 修改当前路径长度 */
(*D)[w] = min+G.arc[k][w];
/* 存放前驱顶点 */
/* P数组存放前驱顶点 完成后即可通过P数组得到最短路径 */
(*P)[w] = k;
}
}
}
}
——cloud over sky
——2020/3/12
最短路径——Dijkstar算法的更多相关文章
- 最短路径——Dijkstra算法
一.相关定义 最短路径:从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径. 地位:Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据 ...
- Dijkstar算法的数学原理
Dijkstar算法是荷兰数学家迪克斯屈拉(or迪杰斯特拉?)在1959年发现的一个算法.是现有的几个求带权图中两个顶点之间最短通路的算法之一.算是一个相当经典的算法了. 迪克斯屈拉算法应用于无向连通 ...
- 单源最短路径——Dijkstra算法学习
每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好 ...
- 网络最短路径Dijkstra算法
最近在学习算法,看到有人写过的这样一个算法,我决定摘抄过来作为我的学习笔记: <span style="font-size:18px;">/* * File: shor ...
- 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?
简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 图中最短路径的算法--dijiska算法C语言实现
#include <stdio.h> #include <stdlib.h> #define ERROR_NO_MEM -1 /*内存不足的错误码*/ #define MAX_ ...
- 最短路径-Dijkstra算法与Floyd算法
一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1 ADE:2 ADCE:3 ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...
- 数据结构实验之图论七:驴友计划 ( 最短路径 Dijkstra 算法 )
数据结构实验之图论七:驴友计划 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Probl ...
随机推荐
- 软件——IDEA 超实用使用技巧分享
前言 工欲善其事 必先利其器 最近受部门的邀请,给入职新人统一培训IDEA,发现有很多新人虽然日常开发使用的是IDEA,但是还是很多好用的技巧没有用到,只是用到一些基本的功能,蛮浪费IDEA这个优秀 ...
- 大富翁 线段树+二分 +dfs
https://csustacm.fun/problem/2033 这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树, 所以出现了bug,主席树的bug是真的难找. ...
- spring mvc实现转发和重定向
转发:服务器端请求的跳转 同一个请求之内 重定向:客户端请求的跳转 两次请求 转发和重定向的区别: 1,转发地址栏不会发生变化,重定向地址栏会发生变化. 2,转发请求的参数不会丢失 重定向参数会丢失. ...
- ssh框架整合时的延迟加载问题(no session问题)的分析以及解决方案
当我们整合完三大框架,并采用hibernate的延迟加载方案时,会出现如下的异常: 现在对这个异常进行分析,如下图所示(模拟通过id查询用户信息的过程): 上图分析了为什么会出现no session的 ...
- abp web.mvc项目中的菜单加载机制
abp中的菜单加载机制 在abp中菜单的定义与我们传统写的框架不一样,它是在编写代码的时候配置,而我们一般写的通用权限管理系统中,是后期在后台界面中添加的.这一点有很大不同.abp关于菜单的定义及管理 ...
- [zoj3623]背包模型
给定n种物品,每种物品需要ti时间生产出来,生产出来以后,每单位时间可以创造wi个价值.如果需要创造至少W个价值,求最少时间. 思路:dp[j]表示用时间j所能创造的最大价值,则有转移方程:dp[j ...
- ASP.NET Core Blazor 初探之 Blazor Server
上周初步对Blazor WebAssembly进行了初步的探索(ASP.NET Core Blazor 初探之 Blazor WebAssembly).这次来看看Blazor Server该怎么玩. ...
- FF按钮点击后表单提交
如果发现<button>提交</button>点击后,所在的表单在ff中自动提交了,则需要添加属性 type='button'! 我也是百度的,记在这里以后方便查看!
- 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- .gitignore 模式匹配
匹配模式前使用 / 表示根目录 匹配模式后使用 / 代表是目录(不是文件) 匹配模式前加 ! 表示取反 * 代表任意个字符 ? 匹配任意一个字符 ** 匹配任意级目录