图的单源最短路径(Dijkstra算法)
在许多路由问题中,寻找图中一个顶点到另一个顶点的最短路径或最小带权路径是非常重要的提炼过程。正式表述为,给定一个带权有向图G = (V, E)
, 顶点s
到v
中顶点t
的最短路径为在边集E
中连接s
到t
代价最小的路径。要做到这一点首先要解决更为一般的单源最短路径问题。在单源最短路径问题中,计算从一个起始顶点s
到其他与之相邻顶点之间的最短路劲。
Dijkstra算法
解决单源最短路径问题的方法之一就是Dijkstra
算法。Dijkstra
算法会生成一颗最短路径树,树的根为起始顶点s
, 树的分支为从顶点s
到图G
中所有其他顶点的最短路径。此算法要求图中的所有权值均为非负数。与Prim
算法类似,Dijkstra
算法也采用贪心算法,它总是将当前看起来最近的最短的边加入最短路径中。
从根本上来说,Dijkstra
算法通过选择一个顶点,并不断探测与之相关的边,类似广度优先搜索,找出当前距离最近的点。
算法流程:
- 求从顶点
a
开始的单源最短路径,就是图中每个点距离a
的最短路。
- 选定
a
,标记访问过了,首先初始化图中各点与a
的距离,在实际代码中一般用一个数组dist[i]
存放这个值,如果暂时不可达,存一个极大值在里面。如图,只有b
,c
直接与a
连接,这时候dist[b]=8
,dist[c]=4
。其它点的dist[i]=NaN,
后面的运算就是不断更新这个dist
数组。
- 再选出
dist
最小的元素扩展,很明显是c
,标记visit
,这时候通过c
点,f
,E
也产生一个新的与a
的距离,这时候更新dist
数组,他们之前与a的距离都是NaN
,当然只要原来与a
的距离大于通过c
与a
的距离,都需要更新。
- 再找出非
visit
中dist
最小的点,找到f
,因为b, d, e
都与f
相邻,这时候比较通过f
后与a
的距离,如果比原来dist
短,就更新dist
。
- 选择顶点
b
。
- 在选择顶点
d, e
后形成最短路径。
Dijkstra
算法实现:
1 function Dijkstra(Graph, source): 2 3 create vertex set Q 4 5 for each vertex v in Graph: // Initialization 6 dist[v] ← INFINITY // Unknown distance from source to v 7 prev[v] ← UNDEFINED // Previous node in optimal path from source 8 add v to Q // All nodes initially in Q (unvisited nodes) 9 10 dist[source] ← 0 // Distance from source to source 11 12 while Q is not empty: 13 u ← vertex in Q with min dist[u] // Source node will be selected first 14 remove u from Q 15 16 for each neighbor v of u: // where v is still in Q. 17 alt ← dist[u] + length(u, v) 18 if alt < dist[v]: // A shorter path to v has been found 19 dist[v] ← alt 20 prev[v] ← u 21 22 return dist[], prev[]
相关推荐
燕哥带你学算法 2020-05-31
chenfei0 2020-02-09
风吹夏天 2019-12-07
Happyunlimited 2019-11-12
humothetrader 2019-06-21
duyifei0 2019-06-21
duyifei0 2019-06-21
zonglinzonglin 2018-08-02
MyronCham 2019-04-26
韦一笑 2011-05-17
lhtzbj 2017-12-12
slxshare 2019-01-17
Masimaro 2020-06-14
rein0 2020-05-03
风吹夏天 2020-05-03
lixiaotao 2020-04-26
horizonheart 2020-04-18
RememberMePlease 2020-04-18
ustbfym 2020-03-03