最短路径算法

1. Dijkstra算法

在正数权重的有向图中求解某个源点到其余各个顶点的最短路径一般可以采用迪杰斯特拉算法(Dijkstra算法)。

1.1 适用场景

  • 单源最短路径
  • 权重都为正

1.2 伪代码

最短路径算法_第1张图片

1.3 示例

问题描述: 计算节点0节点4的最短路径,图路径如下:
最短路径算法_第2张图片
step1: 采用二维表记录0点到其他节点的距离,第一列距离初始化为 ∞ \infty ,第二列记录到达每个节点时,该节点前面的点,主要用于最短路径回溯。
最短路径算法_第3张图片
step2: 0到0的距离是0,为最优路径,标记为对勾,节点0到节点1、7的距离分别为4、8,节点1、7前面的点为节点0,所以在前面点填写0。
最短路径算法_第4张图片
step3: 在未标记的点中选取最小值,最小值为4,对应的节点为1,将其标记为最优路径,标记为对勾,计算最小值节点1的邻居节点。
最短路径算法_第5张图片
经过最小值节点1可以到达邻居节点2、7,到节点2的距离是 4 + 8 = 12 < ∞ 4+8=12<\infty 4+8=12<,所以更新节点2的距离为12,到达节点2时,经过的前面节点为节点1。
经过最小值节点1到达节点7的距离 4 + 11 = 15 > 8 4+11=15>8 4+11=15>8,所以不更新节点7,节点7前面的节点仍为节点0。
step4: 在剩余未标记的点中选取最小值,最小值为8,对应的节点为7,将其标记为最优路径,标记为对勾,计算最小值节点7的邻居节点。
最短路径算法_第6张图片
更新节点6、8,节点6的距离8(节点7的最短距离)+1=9和节点8的距离8(节点7的最短距离)+7=15,前面的节点都为7。以此类推,更新所有的节点。
最短路径算法_第7张图片
最后0到所有节点的最短近距离如下:
最短路径算法_第8张图片
step5: 节点0到节点4的最短距离为21,节点4的前面节点为节点5, 5 → 4 5 \rightarrow 4 54,节点5前面的节点是节点6, 6 → 5 6 \rightarrow5 65, 节点6前面是节点7, 7 → 6 7\rightarrow6 76,节点7前面是节点0, 0 → 7 0\rightarrow7 07,综上所述,最短路径为: 0 → 7 → 6 → 5 → 4 0 \rightarrow 7 \rightarrow6 \rightarrow 5 \rightarrow 4 07654,距离为21。

2. Bellman-Ford算法

Bellman-ford算法适用于单源最短路径,图中边的权重可为负数即负权边,但不可以出现负权环。

2.1 适用场景

  • 单源最短路径
  • 边的权重可为负数即负权边
  • 不可以出现负权环

2.2 伪代码

最短路径算法_第9张图片

2.4 示例

step1: 初始图如下,箭头上的数字表示权重,括号内容含义为:(前面节点,距离),除去源点,其他点的初始距离为 ∞ \infty 1 ◯ − 7 ◯ \textcircled{1}-\textcircled{7} 17表示边的编号。接下来,从节点0到节点n-1开始遍历。
最短路径算法_第10张图片
step2:节点0出发:更新所有节点的权重,节点 0 → 1 0 \rightarrow 1 01为90, 0 → 4 0 \rightarrow 4 04为75, 0 → 3 0 \rightarrow 3 03为80,它们的距离都小于 ∞ \infty ,到达节点的上一个节点都是节点0,更新为(0,距离)。
最短路径算法_第11张图片

step3:节点1出发, 0 → 1 → 2 0 \rightarrow 1 \rightarrow 2 012 90 − 30 = 60 < ∞ 90-30=60<\infty 9030=60<, 由于节点2上一个节点是节点1,所以标记为(1,60)。
最短路径算法_第12张图片
step3:节点2出发,60+10<75,节点4更新为(2,70)
最短路径算法_第13张图片
step4:节点3出发,80-30=50<60,更新节点2为(3,50)。80+10=90>70,无需更新节点4。
最短路径算法_第14张图片
step4:节点4出发,不存在边,无需更新,完成第一遍所有的松弛操作。

step5: 进行第二轮遍历,由于节点 2 → 4 2 \rightarrow 4 24 的和50+10=60<70,更新节点4为(2,60)。
最短路径算法_第15张图片

step6: 第三遍遍历没有任何松弛操作,且3<=n-1=4,说明不存在负权重的环,可以直接返回节点0到其他节点的距离。如果存在松弛操作,最多进行n-1轮遍历,如果第n轮还存在松弛操作,说明存在负权重的环。
最短路径如下图红框所示:
最短路径算法_第16张图片

如果存在负环,示例如下:
最短路径算法_第17张图片
节点2、3、4存在负环,负环会导致无穷迭代。
第1遍遍历结果
最短路径算法_第18张图片
更新节点4为(2,60)
最短路径算法_第19张图片
更新节点3为(4,70)
最短路径算法_第20张图片
更新节点2为(3,40),以此类推,导致无穷迭代。
最短路径算法_第21张图片

3 Floyd算法(待完善)

4 算法特点对比(待完善)

Dijkstra 与Bellmon-ford
(1)Dijkstra为贪心算法,Bellmon-Ford算法不是贪心算法
(2)Dijkstra在有负权的情况下无法工作,Bellmon-Ford算法允许有负权。
(3)Bellmon-Ford算法可以用来判定是否有负权环。
(4)从计算复杂度角度分析,单节点算法首选Dijkstra算法的,它的计算复杂度为 O ( n 2 ) O(n^2) O(n2)

参考资料:
https://blog.csdn.net/weixin_41806489/article/details/126852955
https://www.bilibili.com/video/BV1zz4y1m7Nq
https://www.bilibili.com/video/BV18a4y1A7gv

你可能感兴趣的:(数据结构,算法)