最短路径-迪杰斯特拉算法

整理自《数据结构高分笔记》

1、算法基本思想

设有两个顶点集合S和T,集合S中存放图中已找到最短路径的顶点,集合T存放图中剩余顶点。初始状态时,集合S中只包含源点V0,然后不断从集合T中选取到顶点V0路径长度最短的顶点vu并入集合S中,集合S中每新并入一个顶点,都要修改顶点v0到集合T中顶点的最短路径的长度值。不断重复此过程,直到集合T的顶点全部并入到S中为止。

2、例子解析

上面的说明可能有些抽象,不过通过下面的例子,我相信咱们可以很轻松的明白迪杰斯特拉算法的具体过程。
我们首先定义三个数组:dist[],path[],set[]。
dist[vi]表示当前已找到的从v0到每个终点vi的最短路径的长度。它的初态为:若v0到vi有边,则dist[vi]为边上的权值,否则为无限大。
path[vi]中保存从v0到vi 最短路径上vi的前一个顶点,假设最短路径上的顶点序列为v0,v1,v2……vj,vi,则path[vi]=vj,path[]的初态为,若v0到vi有边,则path[vi]为v0,否则为-1。
set[]为标记数组,set[vi]=0表示vi在T中,即没有被并入最短路径:set[vi]=1表示vi在S中,即已经被并入最短路径,初始时set[v0]=1,其他元素均为0.

我们以下面的图作为例子,来体会下迪杰斯特拉算法的执行过程,我们选择顶点0作为我们的原点:

《最短路径-迪杰斯特拉算法》

初始时:dist数组:dist[0]=0,dist[1]=4,dist[2]=6,dist[3]=6,其他为∞.path[1]=path[2]=path[3]=1,其他元素为-1,set[0]=1,其余为0。我们用g[I,j]表示从I到j的边的权值。

第一步
从当前dist数组中选择长度最短的,即dist[1]=4,所以将顶点1并入S中,set[1]=1,同时以顶点1为中间节点检测剩余顶点:
dist[2] = 6 > dist[1] + g[1,2] = 4 + 1 = 5,因此dist[2]变为5,path[2]变为1,表明要到达顶点2,上一个需要到达的顶点为1。
dist[3]=6 < dist[1] + g[1,3] = ∞,因此dist[3]不变,path[3]不变。
dist[4] = ∞ > dist[1] + g[1,4] = 11,因此dist[4]变为11,path[4]变为1。
dist[5] = ∞ = dist[1] + g[1,5] = ∞,dist[5]不变,path[5]不变。
dist[6] = ∞ = dist[1] + g[1,6] = ∞,dist[6]不变,path[6]不变。

第二步
从当前dist数组中选择长度最短的,即dist[2]=5,所以将顶点2并入S中,set[2]=1,同时以顶点2为中间节点检测剩余顶点(3,4,5,6):
dist[3] = 6 > dist[2] + g[2,3] =∞ ,因此dist[3]不变,path[3]不变。
dist[4] = 11 = dist[2] + g[2,4]=5 + 6 = 11,因此dist[4]不变,path[4]不变。
dist[5] = ∞ < dist[2] + g[2,5] = 5 + 4 = 9 ,因此dist[5]变为9,path[5]变为2。
dist[6] = ∞ = dist[2] + g[2,6] = ∞ ,dist[6]不变,path[6]不变.

第三步
从当前dist数组中选择长度最短的,即dist[3]=6,所以将顶点3并入S中,set[3]=1,同时以顶点2为中间节点检测剩余顶点(4,5,6):
dist[4] = 11 > dist[3] + g[3,4]=∞,因此dist[4]不变,path[4]不变。
dist[5] = 0 > dist[3] + g[3,5] = 11 ,因此dist[5]不变,path[5]不变.
dist[6] = ∞ = dist[3] + g[3,5] = ∞ ,dist[6]不变,path[6]不变..

第四步
从当前dist数组中选择长度最短的,即dist[5]=9,所以将顶点5并入S中,set[5]=1,同时以顶点2为中间节点检测剩余顶点(4,6):
dist[4] = 11 < dist[5] + g[5,4] = 10 ,因此dist[4]变为10,path[4]变为5。
dist[6] = ∞ < dist[5] + g[5,6] = 17 ,因此dist[6]变为17,path[6]变为5。

第五步
从当前dist数组中选择长度最短的,即dist[4]=10,所以将顶点5并入S中,set[4]=1,同时以顶点2为中间节点检测剩余顶点(6):
dist[6] = 17 < dist[4] + g[4,6] = 10 + 6 = 16,因此dist[6]变为16,path[6]变为4。

第六步
从当前dist数组中选择长度最短的,即dist[6]=16,所以将顶点5并入S中,set[6]=1,此时所有的顶点都已经并入最短路径中,所以算法结束。

此时,三个数组的值分别为:

《最短路径-迪杰斯特拉算法》

根据dist数组,我们可以知道从v0出发到各个顶点的最短路径的值,根据path[]数组,我们可以得到v0出发到各个顶点的最短路径包含的顶点顺序,比如我们想要得到从顶点v0 到 v6的最短路径,我们采用倒推法,因为path[6] = 4, 可以知道要到顶点6,需要先到顶点4,在根据path[4] = 5 ,所以需要先到顶点5,以此类推,可以得到从0到6的最短最短路径为:0 – 1 -2 -5 -4-6.
可以看到通过迪杰斯特拉算法,我们可以得到从一个顶点出发到其他各个顶点的最短路径的长度值和经过的顶点路径。

    原文作者:石晓文的学习日记
    原文地址: https://www.jianshu.com/p/83ef202d5a7d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞