迪杰斯特拉(Dijkstra)算法主要是针对没有负值的有向图,求解其中的单一起点到其他顶点的最短路径算法。本文主要总结迪杰斯特拉(Dijkstra)算法的原理和算法流程,最后通过程序实现在一个带权值的有向图中,选定某一个起点,求解到达其它节点的最短路径。 |
举个反例:
当我们使用迪杰斯特拉算法的时候,第一次更新路径长度为1的时候会确定 V 1 − − > V 2 V_{1}-->V_{2} V1−−>V2的最短路径,但是显然这不是最短的。
1.算法原理
迪杰斯特拉(Dijkstra)算法是一个按照路径长度递增的次序产生最短路径的算法。主要特点是以起始点为中心按照长度递增往外层层扩展(广度优先搜索的思想),直到扩展到终点为止。
选择最短路径顶点的时候依照的是实现定义好的贪心准则,所以该算法也是贪心算法的一种。
首先,我们引进一个辅助数组Distance
,它的每个分量D[i]
表示当前所找到的从起始点v0到每个终点vi的最短路径长度。
- 它的初态为:若 v 0 v_{0} v0到 v i v_{i} vi有弧,则 D [ i ] D[i] D[i]为弧上的权值;
否则,置 D [ i ] D[i] D[i]为 ∞ ∞ ∞。
显然,此时长度为
D [ j ] = M i n { D [ i ] ∣ v i ∈ V } D[j]=Min\{D[i]|v_{i}∈V\} D[j]=Min{ D[i]∣vi∈V}
的路径就是从 v 0 v_{0} v0出发长度最短(为1)的一条路径,此时路径为 ( v 0 , v i ) (v_{0},v_{i}) (v0,vi)。 - 那么下一条长度次短的最短路径是哪一条?
假设该次短路径的终点是 v k v_{k} vk,则这条路径要么是 ( v 0 , v k ) (v_{0},v_{k}) (v0,vk),要么是 ( v 0 , v j , v k ) (v_{0},v_{j},v_{k}) (v0,vj,vk),即两者最短的那一条。
其中, v j ∈ S v_{j}∈S vj∈S,S为当前已求得最短路径的终点的集合;V为待求解的最短路径的顶点集合。
问题一:
为什么下一条次短路径要这样选择?(贪心准则的正确性)
不失一般性,假设S为已经求得最短路径的顶点集合,下一条最短路径的终点是 x x x,利用反证法,若此路径有一条顶点不在 S S S中,则说明存在一条终点不在S而长度比此路径长度短的路径,但是这显然是矛盾的,因为我们是按照路径长度递增的次序来产生最短路径