原理
假设有向图G=(V,E)
采用邻接矩阵存储。设置一个二维数组A用于存放当前顶点之间的最短路径长度,分量A[i][j]
表示当前顶点i -> j的最短路径长度。然后,每次添加一个顶点,同时对A的数组进行筛选优化,期间会产生k个A数组。Ak[i][j]
数组代表着从考虑0 -> k
的i -> j 的最小距离,当k 等于全部顶点数的时候,就是已经找出了i -> j
的最短距离。
初始化
1. 二维数组 path [i] [j]
初始化时,i -> j
有路径时,path [i] [j]
= i
(即指向j
的前一个顶点位置); 没有路径时path [i] [j]
初始化为-1
。
2.二维数组A[i][j]
初始化时就等价于边 i -> j
的权值。
算法过程
-
用二维数组A存储最短路径长度:
Ak[i][j]
表示考虑顶点0~k后得出的i -> j
的最短路径长度。An-1[i][j]
表示最终的i -> j
的最短路径长度。
-
用二维数组path存放最短路径:
pathk[i][j]
表示考虑顶点0~k后得出的i -> j
的最短路径。pathn-1[i][j]
表示最终i -> j
的最短路径。
实际上就是从一个个顶点开始分析,从一个到多个的过程中去筛选。初始化数据后,开始添加节点
1
,再去分析如果包含了节点1
以后的各点之间路径是不是有变短,如果有的话就替换,这一遍分析过程被称为二维数组A的更新,也就是Ak数组,k是分析的节点1
。而我们的path数组则是用来存放路径,其实就是i->j
的路径上的j
的上一步的顶点。
3.路径的求解
实现
Floyd算法的C语言实现如下:
void Floyd(MatGraph g) //求每对顶点之间的最短路径
{ int A[MAXVEX][MAXVEX]; //建立A数组
int path[MAXVEX][MAXVEX]; //建立path数组
int i, j, k;
for (i=0;i<g.n;i++)
for (j=0;j<g.n;j++)
{ A[i][j]=g.edges[i][j];
if (i!=j && g.edges[i][j]<INF)
path[i][j]=i; //i和j顶点之间有一条边时
else //i和j顶点之间没有一条边时
path[i][j]=-1;
}
//以上是初始化过程内容
for (k=0;k<g.n;k++) //求Ak[i][j]
{ for (i=0;i<g.n;i++)
for (j=0;j<g.n;j++)
if (A[i][j]>A[i][k]+A[k][j]) //找到更短路径
{ A[i][j]=A[i][k]+A[k][j]; //修改路径长度
path[i][j]=path[k][j]; //修改最短路径为经过顶点k
}
}
DispathFloyd(g, A, path);
}
//以下为输出最短路径的函数
void DispathFloyd(MatGraph g, int A[][MAXV], int path[][MAXV])
{
int i, j, k, s;
int apath[MAXV], d;
for (i = 0; i < g.n; i++)
for (j = 0; j < g.n; j++)
{
if (A[i][j] != INF && i != j)
{
printf("从%d到%d的路径是:", i, j);
k = path[i][j];
d = 0;
apath[d] = j;
while (k != -1 && k != i)
{
d++;
apath[d] = k;
k = path[i][k];
}
d++;
apath[d] = i;
printf("%d", apath[d]);
for (s = d - 1; s >= 0; s--)
printf(",%d", apath[s]);
printf(" 路径长度为:%d
", A[i][j]);
}
}
}
可以看出时间复杂度为O(n^3)