最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(二)—Dijkstra算法(通过边实现松弛:邻接矩阵)

上一节通过Floyd-Warshall算法写了多源节点最短路径问题:

http://blog.****.net/wtyvhreal/article/details/43315705


这一节来学习指定一个点(源点)到其余各个顶点的最短路径。也叫做“单源最短路径”。


例如求下图中1号顶点到2、3、4、5、6号顶点的最短路径。

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

用二维数组e存储顶点之间边的关系,初始值如下:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)


用一个一维数组dis来存储1号顶点到其余各个顶点的初始路程,

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

此时dis数组中的值称为最短路程的“估计值”。


先找一个离1号顶点最近的顶点,是2号顶点,当选择了2号顶点后,dis[2]的值就已经 从“估计值”变为了“确定值”。接下来看2号顶点的出边,有2-3和2-4两条边。先讨论通过2-3能否让1-3号的路程变短,也就是比较dis[3]和dis[2]+e[2][3]的大小。2-4同理。


我们对2号顶点所有出边进行了松弛,完毕后dis数组为:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)


接下来,继续在剩下的3、4、5、6顶点中,选注离1号最近的顶点,是4号,4号的所有出边4-3、4-5、4-6松弛:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

。。。


Dijkstra的主要思想:每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。



步骤:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)


最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)


输入数据:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)

运行结果:

最短路径(2)—Dijkstra算法(通过边实现松弛:邻接矩阵)


这个时间复杂度是O(N^2)

其中每次找到离1号顶点最近的顶点的时间复杂度是O(N),这里可以用“堆”来优化使降低到O(logN),

另外对于边数M少于N^2的稀疏图来说(M<<N^2的图称为稀疏图,而M较大的图称为稠密图),我们可以用邻接表来代替邻接矩阵存储,使得整个时间复杂度优化到O(M+N)logN。

在最坏的情况下M就是N^2,这样的话(M+N)logN要比N^2还要大,但是大多数情况下并不会有那么多边,因此(M+N)logN要比N^2小很多。