一个号称只有5行代码的算法, 由1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。该算法有于求一个带权有向图(Wighted Directed Graph)的任意两点的最短距离的算法,运用了动态规划的思想, 算法的时间复杂度为O(V^3),空间复杂度O(V^2)。
其核心思想是,在两个顶点之间插入一个或一个以上的中转点,比较经过与不经过中转点的距离哪个更短。同时,我们需要引入2个矩阵,一个邻接矩阵D,用来计算每个相邻点的距离,也就是我们的已知条件,第二个矩阵P,则用来表示中间点k的代数。比如说P中p[i,j]的值就是i与j两点的中间点代数。
我们在进行Floyd算法的时候,也要像Dijkstra算法一样,不停的更新这两个矩阵。当我们根据一点规律变化中间点k的时候,也要遍历所有的最小距离和中间点,若D[i,j]<D[i,k]+D[j,k],则矩阵D中的distance[i,j]需要改变成D[i,k]+D[j,k],矩阵P中的P[i,j]要改为k。在遍历掉所有点为中心之后,Floyd算法完成。
这个中转点的思想,我们可以想象现实中的自ekd旅行驾游问题,有的城市间的道路好走,比如存在高速公路,其需要的时间就越短,有的城市间只有原始的泥泞小道,行驶时就很耗时间。
比如A地直接到B地需要7小时
A地经由C地再到B地,则要1+4=5小时
A地经由C地再到D地再到B地,则要1+1+1小时。
换言之,这类似动态规则的背包问题,从A地到B地,每个中转点可以选择也可以不选择,这个逻辑就是对应代码中的松弛操作。要求出所有地方(顶点)之间的最短距离,就需要n^3次松弛操作(三重循环)
Floyd的核心5行代码:
for
需要注意的是,Floyd算法都是围绕顶点展开,因此其表示法只能选择相邻距阵。在相邻距阵中,我们默认所有顶点的权重是无限大,表示它们都不相邻,其实这在Floyd算法有点不对,因为顶点到它自身的距离应该为零,因此这个要改动一下。
其完整实现如下:
class