单源最短路径
最短路径问题也是有向图算法领域中的一个经典问题。从某一点到某一点有多条路径可选,如何选择
其中最‘ 短 ’的一条即为最短路径问题。其中‘短‘的定义很广泛:如果是交通问题,‘短’也
可以被描述为到达目的地耗费的时间;如果是运输问题,‘短’有可以被定义为运输耗费的资金…
最短路径有几个变体,中最为熟知的就是单源最短路径。‘单源’即是从单个源节点出发。
通用算法基本点
算法导论中介绍说,单源节点路径问题有通用的算法解。以下是应用于这个通用算法的基本点。
短(权重)
算法导论中将‘短’抽象表示为权重,每条路径上都带有一个权重。(不应该存在权重和为负值的环路
,详见算法导论P376)
环路
最短路径不应该包含环路。(详见算法导论P376)
最短路径表示
算法导论中规定,对于每个节点,维持一个前驱结点,用以导出最短路径的表示。
松弛操作
对每个节点v, 维持一个属性v.d,用来记录从源节点s到节点v最短权重路径的上界(即当前最小路
径值)。称v.d为源节点s到节点v的最短路径估计。
对一条边的(u,v)的松弛过程为:首先测试一下是否可以对从s到v的最短路径进行改善。测试方
法是将从节点s到节点u之间的最短路径距离加上u与v之间的最短边权重,并与当前的s到v的最短路
径进行比较,如果前者更小,则对v.d和v.π进行更新。松弛步骤可能降低最短路径的估计值v.d并
更新v的前驱属性v.π。
在通用算法基础上具体化的算法都调用次操作,不同的是每条边进行松弛的次数和松弛边的次序有所不同。
Dijkstra算法
Dijkstra算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值。
Dijkstra算法是通用算法中的一个具体化算法。
初始化
初始化有向图的节点:
- 将前驱设为空。
- 最短路径估计设为无穷大。
- 选择源节点
上图选择s为源节点,圆圈中的数值为每个节点的最短估计路径,圆圈上的字母 为节点名
称,边上的数值为权重。
Extract
每次循环提取出所有剩余节点中最短路径估计值最小的节点,表示**从源节点到该节点的
最短路径已被找到**。(提取后,该节点在剩余节点中被去除)
涂黑节点即为所提取出的节点,右边部分即为剩余节点。
松弛(relax)
对于每个提取出的节点u,对每条以u为出发点的边进行松弛操作(relax)。
图中提取出的节点为s,可以看到s有两条以它为出发点的有向边,因此分别更新两条有向边的目的
节点t、y。
重复
重复Extract和松弛(relax)操作,直至剩余节点为空。
结果
灰色描出的有向边即为选出的最‘短’路径。
Code
https://code.csdn.net/snippets/1388077(注:windows8.1,VS2013下编译运行通过)