弗洛伊德算法求的是每一对顶点之间(n->n)的最短路径,而迪杰斯特拉算法求得是某一点到其它顶点(1->n)的最短路径
所以第一种方法就是将迪杰斯特拉算法循环n次。
第二种就是直接运用弗洛伊德算法:
原图:
一,大致过程演示解释
这里只说所有顶点经过A点得到的最短路径(可以先看后面关于方法的解释,再来理解这段话)
- 首先A点经过A得到最短路径,显然可知都不变。
- 然后B点经过A点得到最短路径,即将B点与其它点的连线与BA和A到其他点连线相比较(eg:求AC之间最短路径,将AC与AB+BC相比较。)因为是有向图,所以由图可知B到A无连接,所以仍无变化。
- 再看C点经过A点得到的最短路径:因为CA+AB<CB;CA+AD<CD。所以此时CB的距离变为CA+AB=4,CD=CA+AD=7
- 最后D点经过A点得到的最短路径,因为D点与A点无有向线段连接,所以无变化。
二,实现方法
这一种求最短路径的方法除了需要构造邻接矩阵所需的结构体和函数之外,又入了两个新数组:
int Path[i][j]; //最短路径上顶点j的前一顶点(我感觉这个数组没什么用,加不加都可以)
int Len[i][j]; //i点与j点的最短路径
即表示某点到所求点的距离(如上图中C点经过A到B,因为CA+AB<CB,所以原Len[C][B]等于5变成现在的4)。
- 先构造邻接矩阵,并赋值,该过程类似于图的邻接矩阵储存法类似。
- 先将上面新加入的数组进行赋值。
- 进行弗洛伊德算法:感觉这算法也有点像暴力算法。
就是通过三个遍历进行。先确定一个中间值,然后比较两个顶点是直接连接小还是通过中间值连接小
(eg:比如中间值是B,两个顶点是A和C,则比较AC与AB+BC的值)。
- 然后第三步继续循环循环,直到程序结束。
三,运行截图
循环遍历过程中以四个点为中间点依次遍历的过程
四,代码
#include<iostream>
#include<stdlib.h>
using namespace std;
#define pointMax 100
#define MaxInt 32767
struct AMgroup
{
char VTchart[pointMax]; //顶点表
int AMchart[pointMax][pointMax]; //邻接矩阵
int point, vert; //点,边
};
int AMlocate(AMgroup A, char x)
{
for (int i = 0; i < A.point; i++) //依次输入点的信息
{
if (A.VTchart[i] == x)
{
return i;
break;
}
}
}
void CreatAM(AMgroup &A)
{
cout << "输入邻接矩阵顶点数:"; //第一步
cin >> A.point;
cout << "输入邻接矩阵边数:";
cin >> A.vert;
getchar();
char a[100];
cout << "输入点的信息:"; //第二步
gets_s(a);
for (int i = 0; i < A.point; i++) //依次输入点的信息
{
A.VTchart[i] = a[i];
}
for (int i = 0; i < A.point; i++) //初始换邻接矩阵,边的权值均设为最大
{
for (int j = 0; j < A.point; j++)
{
A.AMchart[i][j] = MaxInt;
}
}
cout << endl;
char v1, v2; int len;
for (int i = 1; i <= A.vert; i++) //构造邻接矩阵
{
cout << "输入第" << i << "条边的两个顶点以及权值:";
cin >> v1 >> v2 >> len;
int m, n;
m = AMlocate(A, v1);
n = AMlocate(A, v2);
A.AMchart[m][n] = len;
}
}
int Path[pointMax][pointMax]; //最短路径上顶点v的前一顶点的序号
int D[pointMax][pointMax]; //记录两点间的最短路径
void Show(AMgroup &A)
{
cout << endl << endl;
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
if (A.AMchart[i][j] == MaxInt)
{
cout << "0" << " ";
}
else
{
cout << A.AMchart[i][j] << " ";
}
}
cout << endl;
}
}
void SP_Floy(AMgroup &A)
{
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
if (A.AMchart[i][j] < MaxInt && i != j) //如果i和j之间有弧
{
Path[i][j] = i;
}
else
{
Path[i][j] = -1;
}
}
}
for (int i = 0; i < A.point; i++)
{
for (int j = 0; j < A.point; j++)
{
cout << endl;
cout << A.VTchart[j] << "经过" << A.VTchart[i] << "点到其他点" << endl;
for (int k = 0; k < A.point; k++)
{
if (A.AMchart[j][i] + A.AMchart[i][k] < A.AMchart[j][k] && j != k)
{
A.AMchart[j][k] = A.AMchart[j][i] + A.AMchart[i][k];
Path[j][k] = Path[i][k];
}
}
Show(A);
}
}
}
int main()
{
AMgroup *A = new AMgroup;
CreatAM(*A);
SP_Floy(*A);
system("pause");
}