Prim算法

 

/*Prim算法:求一个无向连通图的最小生成树的算法,算法本质上利用图的割性质.图的割性质是指:将图的顶点人为地分成互不相交
的集合,这些集合可以通过交叉边连接起来,而连接这些集合的最小交叉边就是最小生成树的边,至于算法的证明在这里就不说明了自己可以上网查
图的一部分代码在其我的其它程序中有说明,就是图的ADT矩阵实现中有介绍,这里值得关注的代码是GRAPHmstV(graph* g)这个函数它是实现Prim算法的主体
*/
#include<stdio.h>
#include<stdlib.h>
static double maxWT=1000.00;
static int* fr , *st;
static double *wt;

#define p g->adj[v][w]
struct edge{int v,w ; double wt;};
edge EDGE(int v,int w , double wt){
    edge e ; e.v = v , e.w = w , e.wt = wt;
 return e;
}
double **MARTXint(int r, int c, double wt){
    int i,j;
 double **t=(double**)malloc(r*sizeof(double*));
 for(i=0;i<r;i++)
  t[i]=(double*)malloc(c*sizeof(double));
 for(i=0;i<r;i++)
  for(j=0;j<c;j++)
   t[i][j]=wt;
  return t;
}
struct graph{int V , E; double **adj; };
graph* graphinit(int V){
   graph *g=(graph*)malloc(sizeof(graph));
   g->V=V , g->E=0;
   g->adj=MARTXint(V,V,maxWT);
   return g;
}
void graphinsert(graph* g,edge e){
   int v=e.v , w=e.w ;
   if(g->adj[v][w]==maxWT) g->E++;
   g->adj[v][w]=g->adj[w][v]=e.wt;
}
void graphshow(graph* g){
   int i,j;
   for(i=0;i<g->V;i++){
   printf("%2d :", i);
   for(j=0;j<g->V;j++)
    if(g->adj[i][j]==maxWT) printf("*  ");
    else printf("%.2lf ",g->adj[i][j]);
    printf("\n");
   }
}
void GRAPHmstV(graph* g){
    int v,w,min;
 st=(int*)malloc(g->V*sizeof(int));
 fr=(int*)malloc(g->V*sizeof(int));                //Prim算法的主体,本质是上是利用图的割性质的
 wt=(double*)malloc((g->V+1)*sizeof(double));      //最后得出的结果是每个结点的父结点,通过这些结点就可以画出一棵最小生成树了
 for(v=0;v<g->V;v++)     
 {st[v]=-1 , fr[v]= v  , wt[v]=maxWT;}           
 st[0]=0 ; wt[g->V]=maxWT;
 for(min=0;min!=g->V;){
    v=min ; st[min]=fr[min];                      //st[min]放的是树中每个结点的父结点比如st[7]=0 , 就表示7的父结点是0
    for(w=0,min=g->V;w<g->V;w++)
     if(st[w]==-1)
     {
      if(p<wt[w]){
      wt[w]=p , fr[w]=v;             //不断地更新边
      }
      if(wt[w]<wt[min]) min=w;     //求出最短的交叉边
     }
 }
}
int main(){
   int v,i,j;
   double Wt;
   scanf("%d",&v);
   graph* g=graphinit(v);
   while(scanf("%d%d%lf",&i,&j,&Wt) && i!=-1 && j!=-1)
    graphinsert(g,EDGE(i,j,Wt));
   printf("显示图中每条边的权值,‘*’表示没有这条边\n");
   graphshow(g);
   printf("最小生成树中每个结点的父结点\n");
   GRAPHmstV(g);
   printf("  ");
   for(i=0;i<g->V;i++)
    printf("%2d " , i);
   printf("\n");
   printf("st");
   for(i=0;i<g->V;i++)
    printf("%2d " ,st[i]);
   printf("\n");

}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值