算法原理
从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径叫做最优路径,解决该问题的方法包括Dijkstra算法、Bellman-Ford算法、Floyd算法和SPFA算法等。
Dijkstra 算法,是由荷兰计算机科学家 Edsger Wybe Dijkstra 在1956年发现的算法,戴克斯特拉算法使用类似广度优先搜索的方法解决赋权图的单源最短路径问题。Dijkstra 算法原始版本仅适用于找到两个顶点之间的最短路径,后来更常见的变体固定了一个顶点作为源结点然后找到该顶点到图中所有其它结点的最短路径,产生一个最短路径树。本算法每次取出未访问结点中距离最小的,用该结点更新其他结点的距离。需要注意的是绝大多数的Dijkstra 算法不能有效处理带有负权边的图。
Dijkstra算法的思路:
- 算法初始,将选择的源点
放进集合
;
- 无自环的源点
到自己的最短路径为0;
- 当顶点
不在集合
中时(此时集合
中仍只有源点
,开始进入循环;
- 将源点
与点
之间的权值赋值给
。由于是有向图,所以当源点
不指向任何其他集合
外的顶点时,
。可以理解为此时从源点
出发,暂时是达到不了
的。不过随着后面集合S的扩充,从源点
出发一定能够到达所有的顶点。此时第一个循环结束。
- 如果集合
不是空集,则进入循环;
- 选出经过第一个循环后的,在集合
中的,且相对于集合
的最短路径中距离最短的那个顶点
;
- 将这个顶点
并入集合
,从而达到扩充集合
的目的;
- 将顶点
并入集合
之后可能会对其他顶点相对于集合
的最短路径长度有影响,所以进入内循环对有影响的路径分支进行更新,即如果从源点
到我们在第6步选出的顶点
的相对于集合
的最短路径的长度再加上顶点
到顶点
之间的距离
还要小于源点
到顶点
的相对于集合
的最短路径长度的话,则将源点
到顶点
的相对于集合
的最短路径更新为源点
到我们在第6步选出的顶点
相对于集合
的最短路径加上顶点
到顶点
之间的权值
。
Dijkstra算法的时间复杂度是。其中:
分别为赋权有向图中的顶点个数和边的个数。Dijkstra算法的时间复杂度是是因为算法总共进行
步,每一步选出一个具有最小
值的顶点放入集合
中,需要
的时间。
而选择基于堆实现的优先队列数据结构,可将Dijkstra算法的时间复杂度降为
Comments NOTHING