数据结构与算法15:单源最短路径弗洛伊德Floyd算法
另一个最短路径算法:
迪杰斯特拉Dijkstra算法
Floyd算法是另一种经典的最短路径算法,不同的是,dijkstra算法仅计算了一个起点出发的最短路径,而floyd算法可以计算全部节点到其他节点的最短路径。相比之下,Floyd算法复杂度为n3,而dijkstra算法为n2。Floyd算法的基本思想也是松弛。这是一个动态规划的经典例子,在求解各个点到其他点的最短路径的过程中往往会有很多的重叠问题,通过一个表D[][]将这些问题保存下来,节省了重复的计算。
这个算法看起来非常简洁。Floyd算法第k次迭代后得到的中间结果的实际含义是:在允许路径经过从第0个到第k个点的条件下,任意两点间的最短路径长度。也就是说当k=0时,d的值和邻接表恰好是一样的,因此初始化时将邻接表复制给d即可。floyd算法需要一个p矩阵保存路径信息,p[i][j]=x的意思是,从i到j的最短路径,先走(i->x),再走(x->j),至于这两段路分别怎么走,那就再查p[i][x]和p[x][j]。
Floyd算法的基本步骤是:
1. 初始化。将邻接表复制给d,同时给p赋初值p
2. 计算允许经过前k个节点的条件下任意两点的最短路径:依次考虑第i个出发的点到第j个点的当前路径,和经过了k这个点的路径长度进行比较,取一个小的,并记录路径数据。
上代码。
void floyd(int g[][], int d[][], int p[][], int n)
{
int i, j, k;
// 初始化
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
d[i][j] = g[i][j];
p[i][j] = j;
}
}
for (k = 0; k < n; ++k)
{
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
if (d[i][j] > d[i][j] + d[k][j])
{
d[i][j] = d[i][k] + d[k][j];
p[i][j] = k;
}
}
}
}
}