用狄克斯特拉算法计算带权最短路径
对于有向带权图中从一个确定顶点(称为源点)到其余各顶点的最短路径问题,狄克斯特拉(Dijkastra)提出了一个按路径长度递增的顺序逐步产生最短路径的构造算法。
狄克斯特拉算法思想
[狄克斯特拉算法思想] 设置两个顶点的集合 S 和 T ,集合 S 中存放已找到最短路径的顶点,集合 T 中存放当前还未找到最短路径的顶点。初始状态时,集合 S 中只包含源点,设为 v0 ,然后从集合 T 中选择到源点 v0 路径长度最短的顶点 u 加入到集合 S 中,集合 S 中每加入一个新的顶点 u ,都要修改源点 v0 到集合 T 中剩余顶点的当前最短路径长度值,集合 T 中各顶点的新的当前最短路径长度值为原来的当前最短路径长度值与从源点过顶点 u 到达该顶点的路径长度中的较小者。此过程不断重复,直到集合T中的顶点全部加入到集合 S 中为止。
对于下图所示的有向带权图给出了狄克斯特拉算法求从顶点A到其余各顶点的最短路径的过程。图中,虚线表示当前可选择的边,实线表示算法已确定包括到集合S中的顶点所对应的边。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/A%E5%88%B0%E5%85%B6%E4%BB%96%E5%AE%9A%E7%82%B9%E7%9A%84%E6%9C%80%E7%9F%AD%E8%B7%AF%E5%BE%84.png)
Emm…懂…懂了吗?
好吧…反正我没看懂 ┑( ̄Д  ̄)┍
让我们换一种打开方式
举一个栗子:起点到终点
下面来看看如何对下面的图使用这种算法。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B91.jpg)
其中每个数字表示的都是时间,单位分钟。为找出从起点到终点耗时最短的路径,你将使用狄克斯特拉算法。
如果你使用广度优先搜索,将得到下面这条段数最少的路径。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B92.jpg)
这条路径耗时7分钟。下面来看看能否找到耗时更短的路径!狄克斯特拉算法包含4个步骤。
- 找出“最便宜”的节点,即可在最短时间内到达的节点。
- 更新该节点的邻居的开销,其含义将稍后介绍。
- 重复这个过程,直到对图中的每个节点都这样做了。
- 计算最终路径。
第一步: 找出最便宜的节点。你站在起点,不知道该前往节点A还是前往节点B。前往这两个节点都要多长时间呢?
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B93.jpg)
前往节点A需要6分钟,而前往节点B需要2分钟。至于前往其他节点,你还不知道需要多长时间。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B94.jpg)
由于你还不知道前往终点需要多长时间,因此你假设为无穷大(这样做的原因你马上就会明白)。节点B是最近的——2分钟就能达到。
第二步: 计算经节点B前往其各个邻居所需的时间。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B95.jpg)
你刚找到了一条前往节点A的更短路径!直接前往节点A需要6分钟。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B96.jpg)
但经由节点B前往节点A只需5分钟!
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B97.jpg)
对于节点B的邻居,如果找到前往它的更短路径,就更新其开销。在这里,你找到了:
- 前往节点A的更短路径(时间从6分钟缩短到5分钟)
- 前往终点的更短路径(时间从无穷大缩短到7分钟)
第三步: 重复!
重复第一步: 找出可在最短时间内前往的节点。你对节点B执行了第二步,除节点B外,可在最短时间内前往的节点是节点A。
![](https://github.com/CANYOUFINDIT/data_structure/raw/master/image/%E8%B5%B7%E7%82%B9%E7%BB%88%E7%82%B98.jpg)
重复第二步: 更新节点A的所有邻居的