最小生成树 -----普里姆(prim)算法+ 邻接矩阵

最小生成树 -----普里姆(prim)算法+ 邻接矩阵

这里采用邻接矩阵的方式存储。
prim算法:用两个集合表示,v集合表示选中的顶点,u-v表示待选的顶点的集合。主要是不断的选则两集合之间边值最小的u-v中的顶点。直到顶点全部选完。

算法的主要思想是定义了两个数组:lowcost[]:用来表示两个集合之间最小的权值边。 lowset[]:用来 表示最小边对应在v集合里的顶点

代码如下:

#include <stdio.h>
#include <malloc.h>
#define inf 330
#define max 50

typedef struct  node{
	int no;
}bnode;//顶点结构体 

typedef struct graph{
	int a[max][max];
	int e,n;
	bnode nu[max];
}G;//邻接矩阵结构体 

//创建邻接矩阵 
void create(G &g, int b[max][max], int n, int e)
{ 
	int i ,j;
	g.e =e;//边数 
	g.n =n;//顶点数 
	for(i = 0; i<n; i++)
	{
		for(j = 0; j <n; j++)
	       g.a[i][j] = b[i][j];	
	}
	for(int i=0; i<n; i++)
	  g.nu[i].no = i;
}

void show(G g)
{
	int i ,j;
	printf("创建的邻接矩阵:\n");
	
	//下面代码段是显示矩阵的行列标识 
	printf("    ");
	for(int i =0; i<g.n; i++)
	printf("%d  ",i);
	printf("\n");
	
	for(i =0; i<g.n; i++)
	{
		printf("%d: ",i); 
		for(j=0; j<g.n; j++)
		{
			if(g.a[i][j] == inf)
				printf(" ∞") ;
			 else
			 	printf(" %d ",g.a[i][j]);
		}
		printf("\n");
	}
	printf("\n%d个顶点,%d条边 \n",g.n, g.e);
}
 
 //普里姆算法
 /*算法的主要思想是贪心的思想,就是局部优到整体。
 这里主要注意两个问题:一个是找顶点问题,二是修改边值问题(修改lowcost[j]) ,前者找顶点是找在U-V集合中找最近,且边值最小的
 后者就是在找到顶点的基础上修改lowcost[j],这里的lowcost[j](j是U-V集合里的顶点)指的是顶点j到集合V的最短的边值,
 刚开始初始化是与0编号顶点连接的权值。
 需要注意的是,如果(U-V)集合里的一个顶点与V集合有多边的时候,lowcost也是选择最喜小的一条。
 */ 
void prim(G g,int v)
{
	int k,min,minweight =0;
	int lowcost[max];//U-V集合的点到V集合点的最短的权值边 
	int lowset[max];//记录U-V集合里点j 最短边 在V集合里另外一端的点 
	//第一个循环初始化lowcost和lowset数组

	for(int i =0; i<g.n; i++)
	{
		lowcost[i] = g.a[v][i];
		lowset[i] = v;
	 } 

	 //这个循环是找到顶点,顶点的范围应该是n-1 
	 for(int i=1; i<g.n; i++)
	 {
	 
	 	min = inf;	 
	 	
	 	//这个for循环,是找到最近的的顶点,这个点最近同时边值相比其他顶点的边值最小 
	 	for(int j = 0; j<g.n; j++)
	 	  if(lowcost[j]!=0 && lowcost[j] < min) //找其他顶点 
	 	  {
	 	  	 min =lowcost[j];
	 	  	 k = j; 
		   }
		   
		printf("边(%d , %d)权为:%d\n",lowset[k],k,min); 
		minweight +=min;
	    lowcost[k] = 0;//将其方法哦V集合中

		//这个for循环,是上面找到的顶点,紧接着就是以该顶点为起始点,修改U-V集合得顶点到V集合的的边值 
		//找其他顶点,找到的顶点如果比原来连接到v集合的lowcost要小,就更新lowcost。 
	    for(int j=0; j<g.n; j++)
	      if(g.a[k][j]!=0&&g.a[k][j]<lowcost[j])
	      {
	      	lowcost[j] = g.a[k][j];
	      	lowset[j] = k;
		   } 
	 }
	 printf("\n普里姆算法生成的权值和最小值为:%d \n",minweight); 
}

int main()
{
	G g; //注意,这里创建的是结构体类型变量,如果是结构体指针的话,创建的矩阵就是链式 
	int a[max][max]={
	             {0,5,8,7,inf,3},
                 {5,0,4,inf,inf,inf},
				 {8,4,0,5,inf,9},
				 {7,inf,5,0,5,6},
				 {inf,inf,inf,5,0,1},
				 {3,inf,9,6,1,0}
				 };
	int  n=6, e=10;
	
	//创建邻接矩阵 
	create(g,a,n,e);
	show(g);
	
	printf("\n普里姆算法求解结果:\n");
	prim(g,0);
	return 0;	
}

程序运行如下:在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值