数据结构与算法:最小生成树Prim算法(C/C++)

###一、算法描述
1.变换图的邻接矩阵为可达性矩阵
2.给最近节点集closest和最小耗费lowcost节点集初始化(相当于把v加入到要维护的节点集中)
3.依次扩大要维护的节点集直到要维护的节点集扩展到图的全部节点按照以下次序
4.找到当前维护节点集邻接所有边中权重最小的边,动态记录
5.输出这条边
6.把边的相邻节点加入维护的节点集
7.利用动态规划方法更新最近的节点和lowcost,执行3
###二、算法实现

void calculate_in_prim(MatGraph*gf,int v)//Calculate minimum spanning tree 
{
	printf("\nPrim:\n");
	int lowcost[MAXMUM] ;//A set that indicate the lowcost of every vertex to the vertex v 
	int close[MAXMUM];//A set that store the closest precurser
	for (int i = 0; i < gf->n; i++)//Very important!It change the matgraph to the accessibility matrix
	{
		if (gf->edge[v][i] == -1&&v!=i)
		{
			lowcost[i] = INT_MAX;
			close[i] = v;
		}
		else if(v!=i)
		{
			lowcost[i] = gf->edge[v][i];
			close[i] = v;
		}
		else//Make every vertex can point to itself
		{
			lowcost[i] = 0;
			close[i] = v;
		}
		
	}
	int min,u;
	for (int k = 1; k < gf->n; k++)//Expand the vertex set that we maintenan 
	{
		min = INT_MAX;
		for (int i = 0; i < gf->n; i++)//Look for the nearest vertex
		{
			if (lowcost[i] != 0 &&min > lowcost[i])//Using lowcost set judge the vertex location
			{
				min = lowcost[i];
				u = i;
			}
		}
		printf("<%d,%d,%d>", close[u], u,lowcost[u]);//Output the edge and its weight		
		lowcost[u] = 0;//Make the new vertex move into the set by assign the array to zero
		for (int i = 0; i < gf->n; i++)//Update the vertex that isn't in the maintenance
		{
			if (lowcost[i] != 0&&gf->edge[u][i]!=-1&&lowcost[i]>gf->edge[u][i])//Update with dynamic programming
			{
				lowcost[i] = gf->edge[u][i];
				close[i] = u;
			}
		}
	}
}

###三、算法分析
首先分析Prim算法的基本思路。算法构造一个需要维护的节点集,并初始化这个节点集仅有v一个节点。在这个节点集合外的点是我们要研究的对象。如果把这个节点集合看成一个超节点,那么这个超节点内部的节点到lowcost必定是0,因为在扩展这个节点集合时,每一条边都是先输出,再加入新节点。所以,这个节点集合中的每一条边一定是最小生成树的一条边。依次采用贪心策略找到与这个超节点邻接的最小权重边,输出后更新除这个节点集合外的节点信息,包括他们的lowcost,closest。lowcost集合是我们寻找邻接边的依据,当我们找到一条边lowcost[i]最小时,我们不难发现,此时要想输出这条边必须找到i节点的前驱,而closest[i]集合正是我们要寻找的前驱。这就说明了建立两个节点集合的必要性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值