C++数据结构-图的多源最短路径弗洛伊德算法

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43323201/article/details/84800426