普利姆算法构造最小生成树——C++

普利姆算法:简单地说就是从一个点开始逐步访问所有顶点,每次经过的边是每一次可以走的所有路径中权值最小的那条边,根据这种方法构造最小生成树。

视频示例如下:

课程 | 人邮社专业自主学习资源库


//如下代码是完整代码,关于普利姆算法的部分有专门标注!

//本博主所发的所有的文章都有完整代码哦!


//今日,将图学结束
//二维数组存储邻接矩阵
//一维数组存储顶点信息
#include<iostream>
using namespace std;
//-----图的邻接矩阵表示----
#define MaxInt 32767    //表示极大值
#define MVNum 100        //最大顶点数
typedef string VerTexType;//假设顶点的数据类型为字符串型
typedef int ArcType;    //假设边的权值类型为字符串型
typedef struct
{
    VerTexType vexs[MVNum];//顶点表
    ArcType arcs[MVNum][MVNum];//邻接矩阵
    int vexnum, arcnum;//图的当前顶点数和边数
}AMGraph;
//采用邻接矩阵表示法创建无向网
/*
1.输入总顶点数和总边数
2.依次输入点的信息并将其存入顶点表中
3.初始化邻接矩阵,使每个权值初始化为极大值
4.构造邻接矩阵,依次输入每条边依附的顶点和其权值,确定两个顶点在图中的位置之后,使相应边赋予相应的权限,
同时使其对称边赋予相同的权值*/
//返回顶点在邻接矩阵中对应的下标
int LocateVex(AMGraph& G, char *v1)
{
    for (int i = 0; i<G.vexnum; i++)
    {
        if (v1 == G.vexs[i])
            return i;
    }
}
void CreateUDN(AMGraph& G)
{
    int i, j, k,w;
    string v1,v2;
    cin >> G.vexnum >> G.arcnum;        //输入总顶点数和总边数
    for (i = 0; i < G.vexnum; ++i)
        cin >> G.vexs[i];        //依次输入点的信息***顶点数组
    for (i = 0; i < G.vexnum; ++i)
        for (j = 0; j < G.vexnum; ++j)
            G.arcs[i][j] = MaxInt;        //初始化邻接矩阵,使每个权值初始化为极大值
    for (k = 0; k < G.arcnum; ++k)        //构造邻接矩阵
    {
        cin >> v1 >> v2 >> w;            //输入一条边依附的顶点及其权值
        i = LocateVex(G, &v1[0]);            //确定v1和v2在G中的位置,即顶点数组的下标
        j = LocateVex(G, &v2[0]);
        G.arcs[i][j] = w;                //边<v1,v2>的权值置为w
        G.arcs[j][i] = G.arcs[i][j];    //置<v1,v2>的对称边<v2,v1>权值为w
    }
}
struct closedge
{
    VerTexType adjex;//顶点 
    ArcType lowcost;//权值 
 }closedge[MVNum];//该数组用来记录从顶点集U到U-V的权值的最小的边 
int Min(struct closedge *p,int G)
{
    int min=100,k;
    for(int i=0;i<G;i++)
    {
        if(p[i].lowcost!=0&&p[i].lowcost<min)
        {
            min=p[i].lowcost;
            k=i;
            }    
    }
    return k;
}
void show(AMGraph G)
{
    for (int i = 0; i < G.vexnum; i++)
    {    
        for (int j = 0; j < G.vexnum; j++)
        {
        //    if (G.arcs[i][j] == MaxInt)
                cout << G.arcs[i][j] << "\t";
        ///    else
        //        cout << G.arcs[i][j] << "\t";
        }
    cout << endl<<endl;
    }
}
//普利姆算法 
void Prim(AMGraph G,char *u)//u为起始顶点 
{
    int k,j,i;
    string u0,v0;
    k=LocateVex(G,&u[0]);//k存储u的下标  
    for(j=0;j<G.vexnum;++j)//对U-V的每一个顶点初始化 
        if(j!=k)
            closedge[j]={u,G.arcs[k][j]};//初始化 
        closedge[k].lowcost=0;
    for(i=1;i<G.vexnum;++i)
    {//其余的n-1个顶点生成n-1条边 
        k=Min(closedge,G.vexnum);//找出边上权最小的边对应的另一个顶点的下标 
        u0=closedge[k].adjex;//找出最小边在U中的点的下标 
        v0=G.vexs[k];//找出最小边在U-V中的点的下标 
        cout<<u0<<"——>"<<v0<<" "<<endl;//输出两点 
        closedge[k].lowcost=0;//初始化,相当于是标记已访问过了 
        for(j=0;j<G.vexnum;++j)
            if(G.arcs[k][j]<closedge[j].lowcost)//找已经存在U中的最小权 
                closedge[j]={G.vexs[k],G.arcs[k][j]};
    }
}
int main()
{
    AMGraph G;
    string v;
    CreateUDN(G);
    show(G);
    cin>>v;
    Prim(G,&v[0]); 
 }
 

输入示例:
6 10
v1 v2 v3 v4 v5 v6    
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v5 6
v3 v4 5
v3 v6 4
v4 v6 2
v5 v6 6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

try again!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值