普里姆算法思路

 算法思想:可取图中任意一个顶点V作为生成树的根,之后若要往生成树上添加顶点W,则在顶点V和W之间必定存在一条边。并且该边的权值在所有连通顶点V和W之间的边中取值最小。

一般情况下,假设n个顶点分成两个集合:U(包含已落在生成树上的结点)和V-U(尚未落在生成树上的顶点),则在所有连通U中顶点和V-U中顶点的边中选取权值最小的边

 C语言代码如下:

//最小生成树 普里姆算法    采用邻接矩阵存储
void MiniSpanTree(MGraph *G)
{
	int min, i, j, k;
	int adjvex[MaxVex];		//保存相关顶点下标
	int lowcost[MaxVex];	//保存相关顶点间边的权值
	lowcost[0] = 0;			//初始化第一个权值为0,即V0加入生成树
	adjvex[0] = 0;			//初始化第一个顶点下标为0

	for (i=1; i<G->numVertexes; ++i)
	{
		lowcost[i] = G->arc[0][i];
		adjvex[i] = 0;				//将v0顶点与之有边的权值存入数组  并初始化都为v0的下标
	}

	for (i=1; i<G->numVertexes; ++i)
	{
		min = INFINITY;

		j = 1;
		k = 0;

		while (j<G->numVertexes)
		{
			//如果两个顶点之间存在边并且权值小于min
			if (lowcost[j]!=0 && lowcost[j]<min)
			{
				min = lowcost[j];
				k = j;
			}

			++j;
		}
		printf("(%d, %d)", adjvex[k], k);	//输出当前顶点边中权值最小的边
		lowcost[k] = 0;						//将当前顶点的权值设为0,表示此顶点已经完成任务
		for (j=1; j<G->numVertexes; ++j)
		{
			if (lowcost[j]!=0 && G->arc[k][j]<lowcost[j])
			{
				lowcost[j] = G->arc[k][j];
				adjvex[j] = k;
			}
		}
	}
}


 首先是变量的定义,min在每次循环中都存放着lowcost数组中最小的权值。

adjvex与lowcost数组中的下标分别对应了该图中的顶点,如下标为1对应了第2个顶点(顶点的序号从0开始)。

例如adjvex[3] = 5  lowcost[3] = 8即表示序号为5的顶点(即第6个顶点)到序号为3(两个数组的下标都为3 即第4个顶点)的顶点的边的权值为8

接着初始化lowcost[0]与adjvex[0]为0,即表示第0号结点加入生成树,lowcost[i] = 0表示第i个结点加入到生成树中

然后 一个循环将adjvex数组的值全都置为0并且将v0到其他顶点的权值都存入lowcost数组中。

一个包含所有顶点的大循环,所有的工作都在该循环体内完成

①假设现在是第一次循环 即第一个顶点加入生成树,第23行~33行,求得所有与该结点相邻的顶点的边上的最小的权值,并将该权值存放min中,而与其相邻的那个顶点的序号存入k中。即找到一个顶点k并且v0到k的权值是所有v0的邻接点中最小的。

/输出当前顶点边中权值最小的边  即输出adjvex[k], k 因为是第一次循环 所有adjvex[k] = 0, k即刚才所得到的那个权值最小的相邻的顶点的序号。即表示adjvex[k]号顶点到k号顶点

③lowcost[k] = 0; 表示 第k号顶点已经加入到生成树种

④第36行~43行  if (lowcost[j]!=0 && G->arc[k][j]<lowcost[j])  如果顶点j没有加入生成树 并且k顶点到j顶点的权值要小于对应的lowcost数组中第j个元素的权值,那么就讲该权值存入Lowcost数组并将j存入adjvex中。也就是说,当我加入了一个k顶点到生成树中以后,那么生成树中必然会多一些k顶点与其邻接点的边出来,那么我要看下这些边上的权值是否有小于lowcost数组中对应位置上的值(初始状态lowcost数组中的值都是v0到各个顶点的边的权值),如果小于那么就说明顶点k到顶点j的边的权值要比V0到j的边的权值小。我们当然要保存这个结果,那么就修改adjvex[j] = k  lowcost[j] =  G->arc[k][j];  即k顶点到j顶点的权值为 G->arc[k][j];  

以后每次加入一个新的顶点都要看其与其邻接点的边上的权值是否要小于lowcost数组中对应顶点的权值。如果小于就修改

然后找到Lowcost数组中最小的权值 并将其与顶点输出

  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
普里姆算法(Prim's Algorithm)和克鲁斯卡尔算法(Kruskal's Algorithm)都是用于解决最小生成树(Minimum Spanning Tree,MST)问题的经典算法。 最小生成树是一个连通图的生成树,它包含了图中所有顶点,并且具有最小的总权重。普里姆算法和克鲁斯卡尔算法都可以用来找到图的最小生成树,但它们的思路和实现方式有所不同。 普里姆算法思路是从一个起始顶点开始,逐步选择与当前生成树连接的权重最小的边,并将其加入到生成树中,直到生成树包含了图中所有的顶点。具体步骤如下: 1. 初始化一个空的生成树,将起始顶点加入生成树中。 2. 重复以下步骤,直到生成树包含了图中所有的顶点: - 选择与当前生成树连接的权重最小的边。 - 将该边连接的顶点加入生成树中。 克鲁斯卡尔算法则是基于边来构建最小生成树的。它首先将图中的所有边按照权重进行排序,然后逐个选择权重最小的边,并判断该边的两个顶点是否属于同一个连通分量(即是否会形成环)。如果不会形成环,则将该边加入到最小生成树中,直到最小生成树包含了图中所有的顶点。具体步骤如下: 1. 初始化一个空的最小生成树。 2. 将图中所有边按照权重进行排序。 3. 重复以下步骤,直到最小生成树包含了图中所有的顶点: - 选择权重最小的边。 - 判断该边的两个顶点是否属于同一个连通分量。 - 如果属于同一个连通分量,则选择下一条边。 - 如果不属于同一个连通分量,则将该边加入最小生成树中,并将两个顶点合并为一个连通分量。 这就是普里姆算法和克鲁斯卡尔算法的基本思路和步骤。它们都可以有效地找到图的最小生成树,但在不同的应用场景下可能有不同的性能表现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值