Dijkstra算法

来源:互联网 发布:c语言ll是什么意思 编辑:程序博客网 时间:2024/05/15 06:08

 

Dijkstra算法

书本上说,先找到一条长度最短的路径,再找到一条次最短的路径。一开始人是不是闷了,你还要了解什么是最短,什么是次最短。我用大白话来描述一下这个过程就是先从源点开始,找到当前离源点最近的点,然后再依据刚得到的离源点最近的点,得到下一个离源点最近的点。是不是这样理解次最短比较舒服些。

算法需要的一些数据结构:

在上边的图上(这个图不是我发明的,是教材上的)有一个带权值的有向图,为了表示这些点之间的距离用了一个二维数组来表示,像上边的第二个图,我们就叫数据G吧

还需要记录从源点到其它点的最短距离值,我们这里假设就是从结点0开始的数据,我们就用数组D吧

算法还需要提供两个集合,一个是S,一个是U。S是用来将已经找到的最短路径的点放到这个集合中;U是还没有将最短路径的点放入到S中的剩余的点。

出于算法考虑,再增加一个数组Prev, Prev是用来存放 要准备加入到集合S中的点 和源点之间最近的点,说的可能有点绕,先往下走吧,程序走完,你应该理解了Prev数组的玄机了。

算法的思路:

(1)       初始化

(2)       从U中找到一个距离最小的点v,将v加入到集合S中,这里找到最小的距离就是指在上边的数组D中,从那些还没有加入到集合S中的点找到最小的值

(3)       因为加入了一个v点,更新其它点和源点之间的路径,更新的思路是,如果v和其它没有加入到集合S中的点好比是m直接相连,那么就比较上边D中的点m的值 和 D中点v的值加上v和m之间的距离值比较,如果后边这个加起来的值比原来D中m的值小,就将原来D中m的值更新为这个比较小的值,同时将v这个结点加到数组Prev中m结点对应的值,这里说明的是v是m结点离源点最近的值

(4)       重复2和3的操作,直到将所有的点都加入到集合S中去,这里的所有有两种情况,第一种是如果U中的结点空了,程序结束了;第二种情况,在程序运行的时候,没有找到最小的距离值,也就是说程序开始会设定一个比较大的权值,代表这个点与源点不能到达。如果程序在运行中,找不到不是这个最大权值的点,就代表剩下的点与源点到达不了,程序也就退出了。

 

 

开始运行程序

初始化

将源点0加入到集合S中去,初始化数组D  这里用#来代替那个无穷大值,表示不可到达

S ( 0 )

D0  D1  D2   D3  D4

0   10   #    30  100

 Prev1  Prev2  Prev3  Prev4

   -1     -1     -1     -1

这里用-1值代表没有前边的点离源点最近

 

 

好吧让程序开始go了

从没有加入到集合S中的点 1 2 3 4中找到距离权值最小的,看上边的数组D中看是1结点最小,那么就将1加入到S中

S(0  1)

因为加入了1这个结点,那么其它结点就可以间接通过结点1到达源点0,开始更新距离数组D,因为只有结点2和1相连,只要更新2的距离就行,2原来到0的距离是#,现在通过1以后,距离变成0到1的距离10加上1到2的距离50变成了60,60比#要小,更新

D0  D1  D2   D3  D4

0   10   60   30  100

     这里看到2结点是通过1来获得到源点0的距离,所以将Prev2的值更新为1

  Prev1  Prev2  Prev3  Prev4

   0      1     -1     -1

 

 

继续循环

从没有加入到集合S中的点2 3 4中找D数组最小的,看上边的3的结点对应的值最小,于是将3加入到S中

S(0  1  3)

同样的判断和3能到达的点的距离然后更新

D2原来的距离60  和 加入3的距离30加上3到2的距离20等于50,50比60小更新;同理,D4原来的距离100 和 加入3的距离30加上3到4的距离60等于90,90比100小,更新

D0  D1  D2   D3  D4

0   10   50   30  90

因为2和4更新的距离是与3相关的,所以Prev数组更新为

Prev1  Prev2  Prev3  Prev4

   0    3      0      3

 

 

继续循环,从没有加入到S中的集合2 4中找最小的距离,2的50比4的90要小,于是将2加入到集合S中

S(0  1  3  2)

同样的判断和2能到达的点的距离然后更新

D4原来的距离90  和 加入2的距离50加上2到4的距离10等于60比较,60比90小更新;

D0  D1  D2   D3  D4

0   10   50   30  60

因为4更新的距离是与2相关的,所以Prev数组更新为

Prev1  Prev2  Prev3  Prev4

   0    3      0      2

 

最后把4结点加入集合S中程序运行终止

 

后边一个问题,怎样知道结点到源点的最短距离走的是哪条线,现在看Prev数据,就拿4来举例吧,Prev4的值为2,那么4到源点最短距离要先经过2,再看Prev2的值为3,那么4到源点最短路径就是要先经过3再经过2才能到达,再看Prev3的值为0,找到源点了,那这样就可以输出4到源点0的最短路径是

0--------3----------2---------4   最短路径从D数组中获得D4为60

 

 

 

 

原创粉丝点击