C++数据结构-普利姆算法最小生成树

#include <iostream>
#define MAXVEX 6       //结点数(初始默认6顶点,更改的话直接在这里修改即可)
#define MAXEDGE 10     //边数(初始默认10条边,更改的话直接在这里修改即可)
#define INFINITY 65535 //表示无穷大
using namespace std;

//普利姆最小生成树原理:
//步骤1:确定s和c两个集合,s放生成树结点,c放其余结点
//步骤2:先选一个结点1放入s,此时结点1在s中,其余结点在c中
//步骤3:在与s中的结点1相邻的结点中选出权值最小的那个结点2放入s中,此时s中有结点1和2
//步骤4:在与s中的结点1(结点2)相邻的结点中选出权值最小的那个结点3放入s中,此时s中有结点1和2和3
//步骤5:以此类推........

//下面代码是无向图的邻接矩阵的普利姆算法
//注意点:下标0的位置都不用,所以要多开辟一个空间
//若改为有向图的邻接矩阵普利姆算法,则:
//1.删除下面的一句代码g.matrix[n][m]=1;

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++)
            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<<"请输入边的信息(形如A B,表示从A到B的一条边):";
        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 prim(AdjMatr &g)
{
    int Min ,i,j,k;
    int adjvex[MAXVEX+1];  //保存相关顶点的下标
    int lowcost[MAXVEX+1]; //保存相关顶点间边的权值
    lowcost[1]=0; //lowcost[i]的值为0,表示结点i已经加入生成树,开始先将结点1加入生成树
    adjvex[1]=1;  //初始化第1个顶点的下标为1(生成树的第一个顶点)
    for(i=2;i<=g.vexNum;i++)
    {   
        lowcost[i]=g.matrix[1][i]; //将与顶点1有关的边的权值存入数组
        adjvex[i]=1;               //初始化都为第一个进入生成树的顶点的下标
    }
    for(i=2;i<=g.vexNum;i++)
    {
        Min=INFINITY; //初始化最小权值为无穷大
        j=2;k=1;
        //因为此时lowcost[1]已经是0,即已在生成树中,所以,这里j从2开始
        while(j<=g.vexNum) //循环全部顶点,找出这一次权值最小的结点
        {   //lowcost权值不为0且权值小于Min
            if(lowcost[j] != 0 && lowcost[j]<Min)
            {
                Min=lowcost[j];
                k=j; //k用来保存这一次最小权值的下标
            }
            j++;
        }
        cout<<"("<<adjvex[k]<<","<<k<<")"<<endl; //输出这一轮的最小边
        lowcost[k]=0;  //每次将结点加进生成树后都要把lowcost设为0
        for(j=2;j<=g.vexNum;j++)//再次循环所有顶点
        {   //因为此时lowcost[1]已经是0,即已在生成树中,所以,这里j从2开始
            if(lowcost[j] != 0 && g.matrix[k][j] <lowcost[j])
            {
                lowcost[j] = g.matrix[k][j];
                adjvex[j]=k;
            }
        }
    }
}
int main()
{
    AdjMatr g;
    initAdjMatr(g);
    setAdjMatr(g);
    prim(g);
    return 0;
}

猜你喜欢

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