对于网图来说,最短路径是指两顶点间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。
迪杰斯特拉(Dijkstra)算法
思路:按路径长度递增的次序产生最短路径,从某一个顶点开始,寻找与当前整体距离最近的顶点,依次找下去,直到到达终点。
代码:
1 |
|
理解上注意:该算法并不会刻意寻找到某个顶点的最短路径,因此不能按照一笔画的思路来理解该算法。
final数组最终为:{1,1,1,1,1,1,1,1,1},它表示所有顶点均完成了最短路径的查找工作。
D数组最终为:{0,1,4,7,5,8,10,12,16},它表示v0到各个顶点的最短路径数,如v0到v8的最短距离为16。
P数组最终为:{0,0,1,4,2,4,3,6,7},它表示最短路径所经过的顶点,P[8]=7的意思是v8的前驱顶点是v7,如v0到v8经过的路径为v8←v7←v6←v3←v4←v2←v1←v0。
可以得到v0到任意一个顶点的最短路径和路径长度,如v0到v8的最短路径中,没有v5,但D[5]=8表示v0到v5的最短路径长度为8,由P数组可得v0到v5经过的最短路径为v5←v4←v2←v1←v0。
时间复杂度为O(n²),若求所有顶点到所有顶点的最短路径则执行n次,时间复杂度为O(n³)。
弗洛伊德(Floyd)算法
原理:
$$
D^0[v][w] = min {D^(-1) [v][w] , D^(-1)[v][0] + D^(-1)[0][w]}
$$
D^0、P^0表示初始数组,D^(-1)、P^(-1)表示经过v1搭桥处理后的数组,依次类推。
即:任意寻找一个顶点,判断以该顶点为桥任意两个顶点之间的距离是否会缩短。
代码:
1 | typedef int Pathmatirx[MAXVEX][MAXVEX]; |
最终结果为:
不难发现,v0所在的列与Dijkstra算法结果完全一致。
如求v4到v7的最短路径,P[4]/[7]=3,P[3]/[7]=6,P[6]/[7]=7,故路径为v4→v3→v6→v7。(markdown中两个方括号表示链接,为了区分我在中间加了/表示二维数组。)
求最短路径的显示代码:
1 | for (int v = 0;v < G.numVertexes;v++) |
时间复杂度为O(n³),面临需要求所有顶点到所有顶点的最短路径时比较方便。