普里姆算法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 100
#define MAXSIZE 10000
typedef int adjmatrix[MAX][MAX];///定义一个邻接矩阵
typedef struct node///边的结构体,也就是边的信息
{
    int from,to;///树的起点和终点
    int weight;///数的权值
}Edge;
int arcnum,n;///arcnum是边的数量,n是顶点的个数,我定义在全局变量就不需要去再传递参数了
void creat_matrix(adjmatrix G);///创建邻接矩阵
void prim(adjmatrix G,Edge *T);///利用prim算法从出发点求邻接矩阵表示的图的最小生成树
void print(Edge *T);///输出
int main()
{
    adjmatrix G;///定义一个邻接矩阵
    Edge T[MAX];///T就是最小生成树
    printf("请输入有顶点数:");
    scanf("%d",&n);///顶点数
    creat_matrix(G);///创建邻接矩阵
    prim(G,T);///prim算法
    print(T);///输出路径和最小成本
    return 0;
}
///创建邻接矩阵
void creat_matrix(adjmatrix G)
{
    int i,j,k,e;
    char x,y;
    for(i=1;i<=n;i++)///初始化矩阵
    {
        for(j=1;j<=n;j++)
            if(i==j)
                G[i][j]=0;///对角线,也就是它本身初始化为0
            else
                G[i][j]=MAXSIZE;///如果不是,都是先初始化一个很大的值
    }
    printf("请输入边的个数:");
    scanf("%d",&arcnum);
    printf("起点 终点 权值:\n");
    for(k=1;k<=arcnum;k++)///给每个边进行赋值
    {
        scanf(" %c %c %d",&x,&y,&e);///这里我定义是字符类型,%c是会读取回车键的,所以我在前面空格一下
        i=x-'A'+1;///A相当于是位置1,赋值到矩阵就得相应转换成整型,不再是字符型
        j=y-'A'+1;///类似
        G[i][j]=e;///这是双向的,i->j的路径长度为e
        G[j][i]=e;///这是双向的,j->i的路径长度为e
    }
}


///利用prim算法从出发点求邻接矩阵表示的图的最小生成树
void prim(adjmatrix G,Edge *T)
{
    int i,j,k,min,u,w,m;
    Edge t;///暂时的
    k=1;
    for(i=1;i<=n;i++)///初始化T的结构体信息,首个顶点指向各个顶点
    {
        if(i!=1)///要那样的话就不能是i=1了  所以有了这个条件
        {
            T[k].from=1;///出发点都是1
            T[k].to=i;///然后1出发到每个顶点
            T[k].weight=G[1][i];///然后把1到各个顶点的权值赋值到T里面
            k++;///然后自增
        }
    }
    for(k=1;k<n;k++)///只要进行n-1次操作就行了
    {
        min=MAXSIZE;///先给min赋值一个很大的值,那么我接下来有进行比较最小,最小的值就会进行更新,这样比较方便
        m=k;///m是这个是现在操作的这个顶点,用另外一个遍历是为了不改变k的值,影响到循环的遍历
        for(j=k;j<n;j++)///从k之后以及k进行比较,找到这其中最小的
        {
            if(T[j].weight<min)///一直更新最小值,直到结束
                min=T[j].weight,m=j;///m=j是最小值的位置,下面要进行再次的比较
        }
        t=T[k];///t就暂时的,T[k]就是最开始的信息,那么我找到了最小值的位置之后就要进行改变,把最小值的信息赋值到k的位置
        T[k]=T[m];///就是变换
        T[m]=t;
        j=T[k].to;///新增加最小生成树T中的顶点序号赋给j
        for(i=k+1;i<n;i++)///修改相关的边,就得让T中以及T外的每个顶点保持一条到现在最短的边
        {
            u=T[i].to;///u就是这个j所指向的顶点
            w=G[j][u];///然后这个w就是代表j->u的权值,也就是接下来的每条边的权值
            if(w<T[i].weight)///如果比之前所赋值的边的权值还小,就进行更改
                {
                    T[i].weight=w;
                    T[i].from=j;///那么进行更改,它的起点也就要赋值成j
                }
        }
    }
}
///输出
void print(Edge *T)
{
    int i,s=0;
    printf("最终生成树:\n");
    for(i=1;i<n;i++)
        {
            s+=T[i].weight;///累加
            printf("%c->%c %d\n",T[i].from+'A'-1,T[i].to+'A'-1,T[i].weight);
        }
    printf("成本为:%d\n",s);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值