数据结构与算法之最短路径-Dijkstra算法
接上文的 最短路径-BFS算法
BFS 算法的局限性
带权路径长度——当图是带权图时,一条路径上所有边的权值之和,称为该路径的带权路径长度之和。
BFS 算法求单源最短路径只适用于无权图,或所有边的权值都相同的图
最短路径问题
- 单源最短路径
- BFS 算法 (无权图)
- Dijkstra 算法 (带权图、无权图)
- 各顶点间的最短路径
- Floyd 算法 (带权图、无权图)
Dijkstra 算法
算法思想
首先观看如下两副图:
初试:
- 从
v
0
v_0
v0开始,初始化三个数组信息如下
final[5]
:标记各顶点是否已找到最短路径dist[5]
:最短路径长度path[5]
:路径上的前驱
第一轮:
- 循环遍历所有结点,找到还没确定最短路径,且 dist 最小的顶点
V
i
V_i
Vi,令
final[i]=true
. - 检查所有邻接自
V
i
V_i
Vi的顶点。若其final 值为false,则更新dist 和path 的信息
第二轮: - 循环遍历所有结点,找到还没确定最短路径,且dist 最小的顶点
V
i
V_i
Vi,令
final[i]=true
. - 检查所有邻接自
V
i
V_i
Vi的顶点。若其 final 值为 false,则更新 dist 和 path 的信息
…N 轮之后…
直到 final 数组全为 true,循环结束
计算机思路
- 初始:
- 若从 v_0 开始,令
final[0]=true;dist[0]=0;path[0]=0
- 其余顶点
final[k]=false;dist[k]=arcs[0][k];
1path[k]=(arcs[0][k]==9999)?-1:0
- 若从 v_0 开始,令
- n-1 轮处理:
- 循环遍历所有顶点,找到还没确定最短路径,且 dist 最⼩的顶点 Vi,令 final[i]=ture。并检查所有邻接⾃Vi 的顶点,对于邻接⾃Vi 的顶点 Vj ,若
final[j]==false
且dist[i]+arcs[i][j] < dist[j]
,则令dist[j]=dist[i]+arcs[i][j]; path[j]=i
。(注:arcs[i][j]
表示 Vi 到 Vj 的弧的权值)
- 循环遍历所有顶点,找到还没确定最短路径,且 dist 最⼩的顶点 Vi,令 final[i]=ture。并检查所有邻接⾃Vi 的顶点,对于邻接⾃Vi 的顶点 Vj ,若
时间复杂度: O ( n 2 ) O(n^2) O(n2)即 O ( ∣ V ∣ 2 ) O(|V|^2) O(∣V∣2)。
如何使用数组信息?
v
0
v_0
v0到
v
2
v_2
v2的最短 (带权) 路径长度为:dist[2]=9
通过 path[5]
可知,v_0 到 v_2 的最短 (带权) 路径:
v
2
v_2
v2<–
v
1
v_1
v1<–
v
4
v_4
v4<–
v
0
v_0
v0
这里需要结合 Prim 算法 一起进行比较,二者比较类似
用于负权值带权图
事实上 v_0 到 v_2 的最短带权路径长度为 5
结论:Dijkstra 算法不适用于有负值的带权图
弧的长度,不存在弧的话那就是无穷或者 9999 特殊大整型 ↩︎