#include <iostream>
#define MAXVEX 9 //结点数(初始默认9顶点,更改的话直接在这里修改即可)
#define MAXEDGE 16 //边数(初始默认16条边,更改的话直接在这里修改即可)
#define INFINITY 65535 //表示无穷大
using namespace std;
//下面代码是无向图的邻接矩阵多源最短路径的弗洛伊德算法
//注意点: 下标0的位置都不用,所以要多开辟一个空间
typedef struct
{
int vexNum; //顶点数
int edgeNum; //边数
int matrix[MAXVEX+1][MAXVEX+1]; //二维数组表示矩阵
char vexinfo[MAXVEX+1]; //存放结点数组的值(如A,B,C,D)
}AdjMatr; //邻接矩阵
/*********************初始化邻接矩阵************************/
void initAdjMatr(AdjMatr &g )
{
g.vexNum = MAXVEX; //顶点数
g.edgeNum = MAXEDGE; //边数
//初始化矩阵信息,初始为,一个不可能的数字表示这两个顶点之间不存在边
for(int i=1;i<=MAXVEX;i++)
{
for(int j=1;j<=MAXVEX;j++)
{
if(i == j)
g.matrix[i][j]=0;
else
g.matrix[i][j]=INFINITY;
}
}
//初始化结点信息,(如A,B,C,D)
for(int i=1;i<=MAXVEX;i++)
{
cout<<"请输入第"<<i<<"个结点的信息:";
cin>>g.vexinfo[i];
}
}
//通过结点信息(A,B,C,D之类)来查找对应矩阵下标
/*********************确定边在矩阵的位置*********************/
void locata(AdjMatr &g,char &vex1,char &vex2, int &m, int &n)
{
for(int i =1;i<=MAXVEX;i++)
{
if(vex1 == g.vexinfo[i])
m=i;
if(vex2 == g.vexinfo[i])
n=i;
}
}
/*********************创建图对应的邻接矩阵************************/
void setAdjMatr(AdjMatr &g)
{
//根据输入的两个顶点,来更新矩阵的值
for(int i=1;i<=g.edgeNum;i++)
{
int weight;//两边之间的权值
char vex1,vex2; //接受输入的两个顶点,来表示从vex1到vex2这条边
cout<<"请输入第"<<i<<"条边的信息(形如A B 7,表示从A到B的一条边权值7):";
cin>>vex1>>vex2>>weight;
int m,n; //m和n是用来接受vex1和vex2所在的下标值,好据此更新矩阵相应位置的值
locata(g,vex1,vex2,m,n);
g.matrix[m][n]=weight;
g.matrix[n][m]=weight;//无向图邻接矩阵对称,减去这句代码就是有向图的邻接矩阵了
}
}
/**********************多源最短路径的弗洛伊德算法************************/
void Floyd(AdjMatr &g, int dist[MAXVEX+1][MAXVEX+1],int pre[MAXVEX+1][MAXVEX+1])
{
//先初始化dist和pre这两个二维数组
for(int i=1;i<=MAXVEX;i++)
{
for(int j=1;j<=MAXVEX;j++)
{
dist[i][j]=g.matrix[i][j]; //初始时,dist[i][j]的值即为对应点间的权值
pre[i][j]=j; //初始化pre[i][j]的值为j
}
}
//开始正式弗洛伊德
for(int k=1;k<=MAXVEX;k++)//k是中转点下标
{
for(int v=1;v<=MAXVEX;v++)//v是起点下标
{
for(int w=1;w<=MAXVEX;w++)//w是终点下标
{
if(dist[v][w]>dist[v][k]+dist[k][w])
{
dist[v][w]=dist[v][k]+dist[k][w];
pre[v][w]=pre[v][k];//路径设置经过下标为k的顶点
}
}
}
}
}
/********************输出多源最短路径***********************/
void ShowFloyd(AdjMatr &g, int dist[MAXVEX+1][MAXVEX+1],int pre[MAXVEX+1][MAXVEX+1])
{
cout<<"弗洛伊德算法多源最短路径如下:"<<endl;
for(int v=1;v<=MAXVEX;v++) //v起点下标
{
for(int w=v+1;w<=MAXVEX;w++) //w终点下标
{
cout<<g.vexinfo[v]<<"->"<<g.vexinfo[w]<<"最短路径长度:"<<dist[v][w]<<" ";
cout<<"具体路径为:"<<g.vexinfo[v];
int k=pre[v][w]; //k中转点下标
while(k != w) //中转点等于终点则表示不用再中转了,输出完毕
{
cout<<"->"<<g.vexinfo[k]; //打印路径顶点
k=pre[k][w]; //获得下一个路径顶点下标
}
cout<<"->"<<g.vexinfo[w]<<endl; //打印终点
}
}
cout<<endl;
}
int main()
{
AdjMatr g;
initAdjMatr(g);
setAdjMatr(g);
int dist[MAXVEX+1][MAXVEX+1];//dist[i][j]的表示从i到j的最短路径长度
int pre[MAXVEX+1][MAXVEX+1]; //pre[i][j]=k,则表示从i到j需要经过k中转
Floyd(g,dist,pre);
ShowFloyd(g,dist,pre); //利用这三个数组输出单源最短路径的具体情况
cout<<"dist数组:"<<endl;
for(int i=1;i<=MAXVEX;i++)
{
for(int j=1;j<=MAXVEX;j++)
{
cout<<dist[i][j]<<" ";
}
cout<<endl;
}
cout<<"pre数组:"<<endl;
for(int i=1;i<=MAXVEX;i++)
{
for(int j=1;j<=MAXVEX;j++)
{
cout<<g.vexinfo[pre[i][j]]<<" ";
}
cout<<endl;
}
return 0;
}
C++数据结构-图的多源最短路径弗洛伊德算法
猜你喜欢
转载自blog.csdn.net/weixin_43323201/article/details/84800426
今日推荐
周排行