算法导论-最小生成树-prim算法

关于最小生成树的prim算法原理这里不多做介绍了。与kruskal算法相比,都是利用了贪心策略来求最小生成树,不同的是:

Kruskal算法中,集合A是一个森林;选择最小的权值边加入到森林。

Prim算法中,集合A则是一棵树;每次加入到A中的安全边永远是连接A和A之外某个结点的边中权重最小的边。相当于树的生长。

下面是Prim算法的代码,里面有详细的注释:

#include<stdio.h>
#include<stdlib.h>
#define n 9//图中点的个数
#define max n*n//图中的边的个数
#define inf 9999//标示无穷大
struct edge{
    int u;//起点
    int v;//终点
    int value;//边的权值
}e[max];
int p[n];//p[i]用于记录依次加入最小生成树的顶点

/*-----------------------------prim算法-----------------------------*/
int prim(int en[][n],int v)
{
    int i,j,k,kk=0,min=inf,count=0;//min标示无穷大,count用于记录最小生成树各边的权值
    int lowcost[n];//lowcost[i]用于记录顶点i到最小生成树t中的顶点的最短路径权值
    int intree[n];//intree[i]用于记录顶点i是否在最小生成树中,1:在;0:不在。
    for(i=0;i<n;i++)//初始化
    {
        if(en[i][v]==inf)//路径不可达
            lowcost[i]=inf;
        else //有可达路径
            lowcost[i]=en[i][v];
        intree[i]=0;
        p[i]=-1;
    }
    intree[v]=1;//标记顶点v为最小生成树中的顶点
    p[0]=v;
    for(i=0;i<n-1;i++)//选择其余的n-1个顶点
    {
        min=inf;
        for(j=0;j<n;j++)//选出到最小生成树t中顶点最短的顶点k
        {
            if(intree[j]==0 && lowcost[j]<min)
            {
                min=lowcost[j];
                k=j;
            }
        }
        count=count+min;//记录权值
        intree[k]=1;
        v=k;
        p[++kk]=k;//记录依次加入最小生成树的顶点
        /**
        **开始时,lowcost[]是记录其他点到v(这时v是根结点)的距离
        **当新加入一个结点k后,令v=k,在剩下的未加入结点中寻找,如果v到某点j的距离小于lowcost[j],更新lowcost[j]
        **这也就是prim算法的贪心策略
        */
        for(j=0;j<n;j++)
        {
            if(intree[j]==0 && en[v][j]!=0 && en[v][j]<lowcost[j])
                lowcost[j]=en[v][j];
        }
    }
    return(count);
}
/*-----------------------------主函数-------------------------------*/
int main()
{
    int i,sum=0;
    char vex;
    //en表示各个点之间的连接情况,为inf表示无边,其他值表示边的权值看 :)
    int en[n][n]={{0,4,inf,inf,inf,inf,inf,8,inf},
            {4,0,8,inf,inf,inf,inf,11,inf},
            {inf,8,0,7,inf,4,inf,inf,2},
            {inf,inf,7,0,9,14,inf,inf,inf},
            {inf,inf,inf,9,0,10,inf,inf,inf},
            {inf,inf,4,14,10,0,2,inf,inf},
            {inf,inf,inf,inf,inf,2,0,1,6},
            {8,11,inf,inf,inf,inf,1,0,7},
            {inf,inf,2,inf,inf,inf,6,7,0}};
    printf("输入最小生成树的构造开始顶点(a,b,c,d,e,f,g,h,i):\n");
    scanf("%c",&vex);
    sum=prim(en,vex-'a');
    printf("最小生成树的代价为:%d\n",sum);
    printf("构造最小生成树依次加入树的顶点为:\n");
    for(i=0;i<n-1;i++)
        if(p[i]!=-1)
            printf("%c -> ",p[i]+'a');
        printf("%c\n",p[i]+'a');

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值