弗洛伊德算法
用于求取连通图中任意点到其他点的最短路径的算法,相比于迪杰斯特拉算法,在代码实现上更加简洁,复杂度系数也要小一些。
算法实现
#include<iostream>
using namespace std;
#define MAX 10000000
//打印路径经过的点
void PrintPath(int** path, int n, int i, int j);
//获取图矩阵
void GetArr(int**& arr, int n, int**& path);
//弗洛伊德算法
void Floyd(int** G, int** path, int n);
//int main()
//{
// int** G = NULL, ** path = NULL;
// int n;
// cin >> n;
// GetArr(G, n, path);
// Floyd(G, path, n);
// for(int i=0;i<n;i++)
// for (int j = 0; j < n; j++)
// {
// cout << G[i][j] << ":";
// if (i != j)
// {
// PrintPath(path, n, i, j);
// cout << endl;
// }
// else
// cout << i << endl;
// }
// /*
// 4
//
// 9999 4 11 9999
// 6 9999 2 9999
// 1 9999 9999 1
// 9999 3 9999 9999
// 一组测试数据
// */
// /*
// from 0 to 1: dist = 4 path : 0 1
// from 0 to 2 : dist = 6 path : 0 1 2
// from 0 to 3 : dist = 7 path : 0 1 2 3
// from 1 to 0 : dist = 3 path : 1 2 0
// from 1 to 1 : dist = 0 path : 1
// from 1 to 2 : dist = 2 path : 1 2
// from 1 to 3 : dist = 3 path : 1 2 3
// from 2 to 0 : dist = 1 path : 2 0
// from 2 to 1 : dist = 4 path : 2 3 1
// from 2 to 2 : dist = 0 path : 2
// from 2 to 3 : dist = 1 path : 2 3
// from 3 to 0 : dist = 6 path : 3 1 2 0
// from 3 to 1 : dist = 3 path : 3 1
// from 3 to 2 : dist = 5 path : 3 1 2
// from 3 to 3 : dist = 0 path : 3
// */
// return 0;
//}
//获取图矩阵
void GetArr(int**& arr, int n,int**& path)
{
arr = new int* [n]; //arr是图的邻接矩阵
path = new int* [n]; //path是图的中间节点,path[i][j]的值代表i 到 j间的节点下标
for (int i = 0; i < n; i++) //如果是path[i][j]是-1则说明i 到 j间无中间路径
{
arr[i] = new int[n];
path[i] = new int[n];
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
cin >> arr[i][j];
path[i][j] = -1; //path初始所有都为-1
}
}
//弗洛伊德算法
void Floyd(int** G, int** path, int n)
{
for(int k=0;k<n;k++) //k作为中间节点
for(int i=0;i<n;i++)
for (int j = 0; j < n; j++)
{
if (G[i][j] > G[i][k] + G[k][j])//如果节点i k j间有路径,且要小于i j间的路径则进行替换
{
G[i][j] = G[i][k] + G[k][j];
path[i][j] = k; //将i到j的中间路径存入k
}
}
}
//打印路径长经过的点
//使用递归实现
void PrintPath(int** path, int n, int i, int j)
{
if (i == j) //i=j说明是节点自己到自己,因此不做输出
{
return;
}
else if (path[i][j] == -1) //到-1时表明前面的中间节点已经递归完毕,因此开始输出上一递归的中间节点
{
cout << i << " " << j << " ";
return;
}
PrintPath(path, n, i, path[i][j]);//递归起始节点和接下来的中间节点
cout << j << " "; //打印终止节点
}