最小生成树prim算法

prim算法(选顶点)
不断选取最小权值的边并把对应的顶点不断并入的过程
过程:
1.随意选取起点:随意选择一个顶点作为起始点(不会影响结果),现在我们设U集合为当前所找到最小生成树里面的顶点,T集合为所找到的边。
2.在前一步的基础上寻找最小权值: 查找一个顶点在U={v1}集合中,另一个顶点在V-U集合中的最小权值
3.继续寻找最小权值:查找一个顶点在U={v1,v2}集合中,另一个顶点在V-U集合中的最小权值
4.每次都选取权值最小的边,但不能构成回路,构成环路的边则舍弃。遇到权值相等,又均不构成回路的边,随意选择哪一条,均不影响生成树结果
5.选取n-1条恰当的边以连通n个顶点

#include "iostream"
using namespace std;
#define MAXSIZE 10000
typedef struct
{
    char vertex[100];     //顶点表
    int arc[100][100];     //边表
    int vertex_num;      //顶点个数
    int arc_num;           //边的数目
}Agraph;
struct
{
    char ver_vex;     //顶点name
    int low_weight;  //权值
}edge[100];
int local_vertex(Agraph G,char v)   //顶点位置信息
{
    for (int i=0;i<G.vertex_num;i++)
    {
        if(G.vertex[i]==v)
        {
            return i;
        }

    }
    return -1;
}
void creat_graph(Agraph &G)     //构造图
{
    int i,j ,k;
    cout<<"输入图的顶点数,边数"<<endl;
    cin>>G.vertex_num>>G.arc_num;
    cout<<endl;
    cout<<"输入顶点信息"<<endl;
    for(i=0;i<G.vertex_num;i++)
    {
        cout<<"顶点name"<<(i+1)<<endl;
        cin>>G.vertex[i];
    }
    cout<<endl;
    for(i=0;i<G.vertex_num;i++)
    {
        for(j=0;j<G.vertex_num;j++)
        {
            G.arc[i][j]=MAXSIZE;      //初始化邻接矩阵
        }
    }

    for(k=0;k<G.arc_num;k++)
    {
        char v1,v2;  //边所对应的两个顶点
        int weight;   //权值
        cout<<"输入两个顶点name和边的权值"<<endl;
        cin>>v1>>v2>>weight;
        i= local_vertex(G,v1);
        j= local_vertex(G,v2);
        G.arc[i][j]=weight;
        G.arc[j][i]=G.arc[i][j]; //生成邻接矩阵(给矩阵赋值)

    }

}
int min(Agraph G)
{
    int index=-1;
    int min=MAXSIZE;
    for(int i=0;i<G.vertex_num;i++)
    {
        if(edge[i].low_weight<min && edge[i].low_weight!=0)
        {
            min=edge[i].low_weight;   //找到最小的边及位置
            index=i;
        }

    }
    return index;
}
//最小生成树prim算法
void prim(Agraph G,char u)
//每次都选取权值最小的边,
// 但不能构成回路,构成环路的边则舍弃。
// 遇到权值相等,又均不构成回路的边,
// 随意选择哪一条,均不影响生成树结果
{
    int i,j,k;
    char u0,v0;
    k= local_vertex(G,u);
    for(j=0;j<G.vertex_num;j++)
    {
        if(j!=k)
        {
            edge[j].ver_vex=u;
            edge[j].low_weight=G.arc[k][j];

        }
    }
    edge[k].low_weight=0;
    for(i=1;i<G.vertex_num;i++)
    {
        k = min(G);  //找出最短边,k是顶点index
        u0 = edge[k].ver_vex; //找出所对应的顶点
        v0 = G.vertex[k];
        cout << u0 << "--->" << v0 << endl;

        edge[k].low_weight = 0;
        for (j = 0; j < G.vertex_num; j++)     //更新数组
        {
            if (G.arc[k][j] < edge[j].low_weight)
            {
                edge[j].ver_vex = G.vertex[k];
                edge[j].low_weight = G.arc[k][j];
            }
        }
    }
}

int main()
{
    Agraph G;
    creat_graph(G);
    cout<<endl;
    for(int i=0;i<G.vertex_num;i++)
    {
        for(int j=0;j<G.vertex_num;j++)
        {
            if(G.arc[i][j]!=MAXSIZE)
            {
                cout<<G.arc[i][j]<<"\t";
            }
            else
            {
                cout<<"INF"<<"\t";
            }
        }
        cout<<endl;
    }
    prim(G,'a');


}


input:
6 8
a
b
c
d
e
f
a b 1
b c 2
c d 3
d e 4
e a 5
c f 6
e f 7
a f 9

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值