【图算法】Dijkstra——最短路径
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。算法要求所有边的权重必须是非负的。
问题:
给定三个集合V
、 E
、 W
,其中,V
存放着所有顶点的index/name
(下面代码里的V
为节点数),E
存放所有边的信息,W
存放着E
中对应边的权重(下面代码里把E
和W
合并到在一起了)。现在给出V
中的一个顶点A
,求从A
出发到其他顶点的最短路径,即经过边的权重和最小。
基本思路:
- 建立优先队列
pq
(小顶堆),队列里存储在当前条件下(表示以后可能还会被更新)离源点最近距离的节点及其距离(距离是为了供优先队列比较大小用),初始只有源点,其距离值为0
;还需要一个dist
数组以及visited
数组,数组长度均为节点个数;dist
用来记录当前状态下各个节点离源点的最短路径,初始除源点外的值为无穷大,源点的值为0
;visited
用来记录各个节点是否已经被优先队列弹出过,若为True
则表示当前节点被弹出过。 - 如果优先队列不为空,则弹出优先队列队顶元素,即下一个已经更新过最短路径的节点,如果该节点已经被访问了,即表示在弹出该节点之前该节点有一个比当前最短路径更近的情况被弹出过,则此情况应该丢弃。这也说明我们每次加入优先队列的元素不一定就是最短路径的情况,但是优先队列优先弹出最短路径,这也是为什么我们用优先队列而不是普通队列的原因。
- 如果弹出的节点之前没有被访问过/弹出过,那么该节点的最短路径就被确定了,然后遍历与该节点直接相连的节点,并更新这些节点的最短路径。
- 如果优先队列为空,则说明所有节点的最短路径都已经被确定了,结束循环。
原始思路1:
- 遍历V - S中的所有点,求出从初始点A只经过S中顶点到达该点的路径权重和dist,若不存在路径,则dist设置为$\infty$;
- 找出第一步中的最小的dist,将该dist对应的顶点放入S中,该dist值放入U中;
- 重复1、2直到V等于S为止。
原始思路2:
- 遍历S中的点,找出所有E中从该点出发但是终点不在S中的边,算出对应的dist;
- 找出第一步中的最小dist,将该dist对应的顶点放入S中,该dist值放入U中;
- 重复1、2直到V等于S为止。
Python 参考源码:
1 | import sys |
C++:
1 |
|