Floyd算法和Dijkstra算法规划最短路径
Floyd算法
Floyd算法思想:
弗洛伊德(Floyd)算法又称插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法。算出来的结果是所有的节点到其余各节点之间的最短距离。
通用步骤如下
1.设图顶点数为N。首先需要准备一个长度为N的距离矩阵S,矩阵S中的元素a[i][j]=sum的表示顶点i到顶点j的最短路径为sum;
2.对S矩阵进行初始化,距离矩阵S中顶点a[i][j]的值为顶点i到顶点j的直接权值;
3.对S矩阵循环进行N次更新,在第k次更新时,如果S矩阵的a[i][j] > a[i][k]+a[k][j],那么更新a[i][j]=a[i][k]+a[k][j]。循环更新完毕,则算法完成,所有的节点到其余各节点之间的最短距离已经找到了。
相比于Dijkstra 算法,Floyd算法支持带有负权边的图,但是不能解决带有“负权回路”(或者叫“负权环”)的图,实际上如果一个图中带有“负权回路”那么这个图则没有最短路径。
伪代码
枚举顶点k ∈ [1,n]
以顶点k为中介点,枚举所有顶点对i和j(i ∈ [1,n],j ∈1[1,n])
如果dis[i][k] + dis[k][j] <dis[i][j]成立
赋值dis[i][j] = dis[i][k] + dis[k][j]
Dijkstra算法
Dijskra算法思想:
Dijkstra算法并不是一下子就求出了起点到终点的最短路径,而是采用的是贪心算法策略,一步步求出它们之间顶点的最短路径,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得到起点和终点的最短路径。
通用步骤如下:
1.指定两个集合S和U。S的作用是记录已求出最短路径的顶点,而U则是记录还未求出最短路径的顶点,以及这些顶点到起始顶点的权。
2.指定一个起始顶点A,存入集合S中,其他顶点以及到顶点A的权存入集合U中,从U中找出并移除路径最短的顶点B,并将其加入到S中,并且更新U中对应的路径权值(更新源点将新加入节点作为中间节点到达其它节点的距离);重复该操作直到遍历所有顶点,此时S中的集合就是起点A到其他各个顶点的最短路径。
伪代码
// 初始化,设从0开始
for i=[0,n)
dist[i] = map[0][i]
visit[0] = true;
for i=[1,n)
// 寻找最短路径(s,t),同时把t加入S集合
min = MAX_VALUE
for j=[0,n)
if !visit[j] && dist[j]<min
min = dist[j]//记录最小值和最小值的下标
min_j = j
visit[j] = true
// 松弛边(t,v),其中v为顶点
for k=[0,n)
if !visit[k] && dist[k]>dist[j]+tab[j][k]
dist[k] = dist[j]+tab[j][k]