【图论】Dijkstra算法求最短路

一、Dijkstra算法简介

Dijkstra算法是由河南荷兰计算机科学家狄克斯特拉(Dijkstra)于1959年提出的,因此又叫狄克斯特拉算法。

二、初识Dijkstra算法

在使用Dijkstra算法求最短路时,需要用到三个辅助数组:
v i s x vis_x visx:布尔数组,给 x x x 号结点打标记。初始化为 0 0 0。
s t e p x step_x stepx:记录从固定起点到 x x x 号结点的最短路径,初始化为 + ∞ +\infty +∞。
p r e x pre_x prex:记录 x x x 号结点的前一个结点,如果不理解前一个结点是什么意思,第三部分模拟过程中会讲解。

三、模拟Dijkstra算法求最短路径长度

首先看下面的图5。

图5

假设我们要求从 0 0 0 号结点到 4 4 4 号结点的最短距离,下面是模拟过程:

  1. 初始化 v i s vis vis 和 s t e p step step 数组,记录起点 s t e p 0 = 0 step_0=0 step0=0;
  2. 找到目前未被标记的 s t e p step step 值最小的结点 0 0 0,标记 v i s 0 = 1 vis_0=1 vis0=1, 0 0 0 号结点的邻接点有 1 1 1 和 7 7 7,边权分别为 4 4 4 和 8 8 8,记录 s t e p 1 = m i n ( s t e p 1 , s t e p 0 + 4 ) = 4 step_1=min(step_1,step_0+4)=4 step1=min(step1,step0+4)=4, s t e p 7 = m i n ( s t e p 7 , s t e p 0 + 8 ) = 8 step_7=min(step_7,step_0+8)=8 step7=min(step7,step0+8)=8, p r e 1 = 0 pre_1=0 pre1=0, p r e 7 = 0 pre_7=0 pre7=0;
  3. 找到目前未被标记的 s t e p step step 值最小的结点 1 1 1,标记 v i s 1 = 1 vis_1=1 vis1=1, 1 1 1 号结点的邻接点有 2 2 2 和 7 7 7,边权分别为 8 8 8 和 11 11 11,记录 s t e p 2 = m i n ( s t e p 2 , s t e p 1 + 8 ) = 12 step_2=min(step_2,step_1+8)=12 step2=min(step2,step1+8)=12, s t e p 7 = m i n ( s t e p 7 , s t e p 1 + 11 ) = 8 step_7=min(step_7,step_1+11)=8 step7=min(step7,step1+11)=8, p r e 2 = 1 pre_2=1 pre2=1(PS:此处因为 8 ≤ 15 8 \leq 15 8≤15,所以无需对 s t e p 7 step_7 step7 和 p r e 7 pre_7 pre7 的值进行修改);
  4. 找到目前未被标记的 s t e p step step 值最小的结点 7 7 7,标记 v i s 7 = 1 vis_7=1 vis7=1, 7 7 7 号结点的邻接点有 1 1 1、 6 6 6 和 8 8 8,边权分别为 11 11 11、 1 1 1 和 7 7 7,记录 s t e p 1 = m i n ( s t e p 1 , s t e p 7 + 11 ) = 4 step_1=min(step_1,step_7+11)=4 step1=min(step1,step7+11)=4, s t e p 6 = m i n ( s t e p 6 , s t e p 7 + 1 ) = 9 step_6=min(step_6,step_7+1)=9 step6=min(step6,step7+1)=9, s t e p 8 = m i n ( s t e p 8 , s t e p 7 + 7 ) = 15 step_8=min(step_8,step_7+7)=15 step8=min(step8,step7+7)=15, p r e 6 = 7 pre_6=7 pre6=7, p r e 8 = 7 pre_8=7 pre8=7;
  5. 找到目前未被标记的 s t e p step step 值最小的结点 6 6 6,标记 v i s 6 = 1 vis_6=1 vis6=1, 6 6 6 号结点的邻接点有 5 5 5、 7 7 7 和 8 8 8,边权分别为 2 2 2、 1 1 1 和 6 6 6,记录 s t e p 5 = m i n ( s t e p 5 , s t e p 6 + 2 ) = 11 step_5=min(step_5,step_6+2)=11 step5=min(step5,step6+2)=11, s t e p 7 = m i n ( s t e p 7 , s t e p 6 + 1 ) = 8 step_7=min(step_7,step_6+1)=8 step7=min(step7,step6+1)=8, s t e p 8 = m i n ( s t e p 8 , s t e p 6 + 6 ) = 15 step_8=min(step_8,step_6+6)=15 step8=min(step8,step6+6)=15, p r e 5 = 6 pre_5=6 pre5=6;
  6. 找到目前未被标记的 s t e p step step 值最小的结点 5 5 5,标记 v i s 5 = 1 vis_5=1 vis5=1, 5 5 5 号结点的邻接点有 2 2 2、 3 3 3、 4 4 4 和 6 6 6,边权分别为 4 4 4、 14 14 14、 10 10 10 和 2 2 2,记录 s t e p 2 = m i n ( s t e p 2 , s t e p 5 + 4 ) = 12 step_2=min(step_2,step_5+4)=12 step2=min(step2,step5+4)=12, s t e p 3 = m i n ( s t e p 3 , s t e p 5 + 14 ) = 25 step_3=min(step_3,step_5+14)=25 step3=min(step3,step5+14)=25, s t e p 4 = m i n ( s t e p 4 , s t e p 5 + 10 ) = 21 step_4=min(step_4,step_5+10)=21 step4=min(step4,step5+10)=21, s t e p 6 = m i n ( s t e p 6 , s t e p 5 + 2 ) = 9 step_6=min(step_6,step_5+2)=9 step6=min(step6,step5+2)=9, p r e 3 = 5 pre_3=5 pre3=5, p r e 4 = 5 pre_4=5 pre4=5;
  7. 找到目前未被标记的 s t e p step step 值最小的结点 2 2 2,标记 v i s 2 = 1 vis_2=1 vis2=1, 2 2 2 号结点的邻接点有 1 1 1、 3 3 3、 5 5 5 和 8 8 8,边权分别为 8 8 8、 7 7 7、 4 4 4 和 2 2 2,记录 s t e p 1 = m i n ( s t e p 1 , s t e p 2 + 8 ) = 4 step_1=min(step_1,step_2+8)=4 step1=min(step1,step2+8)=4, s t e p 3 = m i n ( s t e p 3 , s t e p 2 + 7 ) = 19 step_3=min(step_3,step_2+7)=19 step3=min(step3,step2+7)=19, s t e p 5 = m i n ( s t e p 5 , s t e p 2 + 4 ) = 11 step_5=min(step_5,step_2+4)=11 step5=min(step5,step2+4)=11, s t e p 8 = m i n ( s t e p 8 , s t e p 2 + 2 ) = 14 step_8=min(step_8,step_2+2)=14 step8=min(step8,step2+2)=14, p r e 3 = 5 pre_3=5 pre3=5, p r e 8 = 2 pre_8=2 pre8=2;
  8. 找到目前未被标记的 s t e p step step 值最小的结点 8 8 8,标记 v i s 8 = 1 vis_8=1 vis8=1, 8 8 8 号结点的邻接点有 2 2 2、 6 6 6 和 7 7 7,边权分别为 2 2 2、 6 6 6 和 7 7 7,记录 s t e p 2 = m i n ( s t e p 2 , s t e p 8 + 2 ) = 12 step_2=min(step_2,step_8+2)=12 step2=min(step2,step8+2)=12, s t e p 6 = m i n ( s t e p 6 , s t e p 8 + 6 ) = 9 step_6=min(step_6,step_8+6)=9 step6=min(step6,step8+6)=9, s t e p 7 = m i n ( s t e p 7 , s t e p 8 + 7 ) = 11 step_7=min(step_7,step_8+7)=11 step7=min(step7,step8+7)=11;
  9. 找到目前未被标记的 s t e p step step 值最小的结点 3 3 3,标记 v i s 3 = 1 vis_3=1 vis3=1, 3 3 3 号结点的邻接点有 2 2 2、 4 4 4 和 5 5 5,边权分别为 7 7 7、 9 9 9 和 14 14 14,记录 s t e p 2 = m i n ( s t e p 2 , s t e p 3 + 7 ) = 12 step_2=min(step_2,step_3+7)=12 step2=min(step2,step3+7)=12, s t e p 4 = m i n ( s t e p 4 , s t e p 3 + 9 ) = 21 step_4=min(step_4,step_3+9)=21 step4=min(step4,step3+9)=21, s t e p 5 = m i n ( s t e p 5 , s t e p 3 + 7 ) = 14 step_5=min(step_5,step_3+7)=14 step5=min(step5,step3+7)=14;
  10. 找到目前未被标记的 s t e p step step 值最小的结点 4 4 4,标记 v i s 4 = 1 vis_4=1 vis4=1, 4 4 4 号结点的邻接点有 3 3 3 和 5 5 5,边权分别为 9 9 9 和 10 10 10,记录 s t e p 3 = m i n ( s t e p 3 , s t e p 4 + 9 ) = 19 step_3=min(step_3,step_4+9)=19 step3=min(step3,step4+9)=19, s t e p 5 = m i n ( s t e p 5 , s t e p 4 + 10 ) = 11 step_5=min(step_5,step_4+10)=11 step5=min(step5,step4+10)=11;
  11. 此时我们发现,所有结点都已经被标记过,结束搜索,起点 0 0 0 到终点 4 4 4 的最短距离为 s t e p 4 = 21 step_4=21 step4=21。

四、模拟Dijkstra算法求最短路径

仍以上面的图5为例,搜索过程略。

从终点 x = 4 x=4 x=4 往回遍历,每遍历到一个结点就将其入栈,然后 x = p r e x x=pre_x x=prex。当遍历到起点 0 0 0 入栈后,结束遍历,输出栈。

得到结果 0 → 7 → 6 → 5 → 4 0 \rightarrow 7 \rightarrow 6 \rightarrow 5 \rightarrow 4 0→7→6→5→4。

代码将于2024年九月底完成,目前不予展示。

如果博客有错误,请联系我,我会尽快修正!鲁A济南车!

相关推荐
莫叫石榴姐1 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
茶猫_2 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
Hera_Yc.H3 小时前
数据结构之一:复杂度
数据结构
肥猪猪爸4 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
linux_carlos4 小时前
环形缓冲区
数据结构
readmancynn4 小时前
二分基本实现
数据结构·算法
萝卜兽编程4 小时前
优先级队列
c++·算法
Bucai_不才4 小时前
【数据结构】树——链式存储二叉树的基础
数据结构·二叉树
盼海4 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步4 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表