prim算法改编,C语言,可将顶点保存到数组,并可读取文件

1.在prim,yprim的基础上改编而来
2.按照老师课件上思想编写
3.加入了二维数组T[MAX][2],用来存放最小生成树的最终选择最小权值的节点信息
  利用for循环可查看:
   for(i=1;i<n;i++){//输出存放在数组中的最小生成树边集
     printf("%d %d\n",T[i][1],T[i][2]);
   }
4.arcs[MAX][MAX];
5.没有将终点信息赋值给一个数组
     lowcost[MAX];终点         lowcost[i]记录以i为终点的边的最小权值,当lowcost[i]=0时表示终点i加入生成树;
     因为它是可要可不要的,要的话程序看起来会比剑清楚,建议要
     因老师给的课件上没有,所以此程序中没有用到,
     对比用处:lowcost[j]<min
               arcs[j][nearly[j]]<min


6.nearly[MAX];
     类似与mst[MAX]起点      mst[i]记录对应lowcost[i]的起点,当mst[i]=0时表示起点i加入生成树
     但是与mst[MAX]还是不同,因为他不必要代表起点,(理解为起点也可)仅仅用1/0表示在不在集合中就可以了

7.默认选择1号节点加入生成树,从2号节点开始初始化



8.将下面数据保存到1.txt


6 10 
1 2 10
1 4 30
1 5 45
2 3 50
2 5 50
2 6 25
3 5 35
3 6 15 
4 6 20 
5 6 55



#include <stdio.h>
#define INFINITY 0x7fffffff
#define MAX 100//最大顶点数


int arcs[MAX][MAX];






int Prim(int arcs[][MAX],int n){
int i,j,k;
int mincost=0;
int T[MAX][2];
int nearly[MAX];//nearly(j)是生成树中离j(不在生成树中)最近的点
for(i=2;i<=n;i++){//初始化


nearly[i]=1;//默认从节点1开始
}
nearly[1]=0;



for(i=1;i<n;i++){//找最小生成树的边
int min=INFINITY;
int minid=0;


for(j=2;j<=n;j++){
if(arcs[j][nearly[j]]<min&&nearly[j]!=0){//j是终节点,nearly[j]是初始节点,找不在生成树中的节点j,使离nearly[j](树中节点)最近
min=arcs[j][nearly[j]];//最近的边的权值
minid=j;//哪个j离树中节点nearly[j]最近
}
}
//printf("%d\n",min);
//printf("%d\n",minid);
T[i][1]=minid;
//printf("%d\n",nearly[minid]);
T[i][2]=nearly[minid];//将这最小权值边上的两个点存入数组中
mincost+=min;
printf("%d %d %d",T[i][1],T[i][2],min);
printf("\n");
nearly[minid]=0;//一旦找到下一个权值最小的节点另nearly=0,使其加入树中




for(k=2;k<=n;k++){//修改其余不在树中的节点到树中节点的最小权值,这是由于加入了新的节点而使原来到树中节点的距离改变,可能到新的节点的距离是最小的了
if(arcs[k][nearly[k]]>arcs[k][minid]){//如果不在树中的节点k到开始在树中节点nearly[k]的权值,大于加入新节点minid后,k到minid的权值,
nearly[k]=minid;//则修改与k节点有最小权值的树中节点nearly[k]的值
}
}


}
for(i=1;i<n;i++){//输出存放在数组中的最小生成树边集
printf("%d %d\n",T[i][1],T[i][2]);
}
return mincost;
}
int main()
{

int i, j, m, n,p,q;
int minCOST;



FILE  *fp;
    
fp=fopen("1.txt", "r"); 
printf("图的节点数为:");
fscanf(fp, "%d", &p);        
    printf("%d", p);
printf("图的边数为:");
fscanf(fp, "%d", &q);        
    printf("%d", q);


    printf("\n"); 





for (i = 1; i <= p; i++)//节点数,构造二维数组
{
for (j = 1; j <= p; j++)
{
arcs[i][j] = INFINITY;
}
}


    //printf("输入读取的边数");
//scanf("%d",&n);
 
/* 读取边信息 */
for (i = 1; i <= q; i++)//边数
{
 fscanf(fp,"%d", &m);
 fscanf(fp,"%d", &n);
 fscanf(fp,"%d", &arcs[m][n]);
 arcs[n][m]=arcs[m][n];
 printf("%d %d %d\n", m,n,arcs[m][n]);
 
}
printf("\n");




minCOST=Prim(arcs,p);
printf("最小生成树的权值和为:%d",minCOST);




return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值