Floyd算法(解决任意两点间的最短路径,可以正确处理有向图或负权值的最短路径问题):
时间复杂度O(N3),空间复杂度O(N2);
算法思想:
Floyd算法是一个经典的动态规划算法;首先我们的目标是计算顶点i到j的最短路径,从动态规划角度来看:
从节点i到节点j的最短路径不外乎两种可能:1)直接从i到j; 2) i经过若干节点再到j;所以我们可以这样来计算i j之间的最短距离:对于每一个结点k,我们判断Dist(i,k)+Dist(k,j)<Dist(i,j)是否成立,如果成立,则证明从i到k,再从k到j的距离比直接从i到j的距离短,所以我们更新Dist(i,j)=Dist(i,k)+Dist(k,j); 这样,遍历完所有的k值,则得到最终从i到j的最小距离。
Floyd算法过程:
1、用D[i][j]记录每两个顶点之间的距离;
2、依次扫描每一个顶点k,以该点为基准,判断从i经过k,再到j的距离是否小于D[i][j],若是则更新D[i][j]=D[i][k]+D[k][j];
精髓:依次扫描每一点(k),并以该点作为中介点,计算出通过k点的其他任意两点(i,j)的最短距离,这就是floyd算法的精髓!同时也解释了为什么k点这个中介点要放在最外层循环的原因.
typedef struct
{
char vertex[MAXVER];
int edges[MAXVER][MAXVER];
int n, e;
}MGraph;
void Floyd(MGraph g)
{
int D[MAXVER][MAXVER];
int path[MAXVER][MAXVER];
int n = g.n;
for (int i = 0; i < n; ++i) //初始化
{
for (int j = 0; j < n; ++j)
{
D[i][j] = g.edges[i][j];
path[i][j] = -1;
}
}
for (int k = 0; k < n; k++) //注意:一定要理解为什么把k放在最外层的循环,而不放在最内层!!
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (D[i][j]>D[i][k] + D[k][j])
{
D[i][j] = D[i][k] + D[k][j];
path[i][j] = k;
}
}
}
}
}