最小生成树算法之Prim

这个是通过考察顶点的关系来生成最小树的:

  • 首先选取任意的一个顶点来做当前树的第一个顶点。
  • 考察图中剩下的其他顶点与当前树的距离,选取距离最短的一个顶点加入当前树中。
  • 重复上一步,直到所有的顶点已经加入到树中。

关键是怎么考察图中其他顶点与树的距离,这里树的距离是我自己定义的,就是当前顶点Vi的所有边中可以与树中顶点连接的边,其中权值即距离最小的边就是加入Vi到树中要选取的路径。


我们可以声明两个数组一个数组是weightSign用来表示当前所以可与树链接的边的权值,weightSign[k]表示编号为k的顶点Vk与树的最短边的权值(如果weightSign[k]=0,那么说明Vk就在树中了,如果weightSign[k]=∞,说明Vk不能加入到树中)。我们还需要知道Vk顶点与树中的哪个顶点可以连接,还需要另外一个数组vertexSign,vertexSign[k]就表示Vk与当前树中的顶点V(vertexSign[k])的距离最短


可以得知weightSign数组的大小与图中顶点的数目相同,vertexSignweightSign长度相同。假设树中已经有n个顶点了,下面考虑如何将选取第n+1个顶点。由于weightSign[k]表示编号为k的顶点与树的距离,我们找到距离最小的一个点,就可以了,那么新加入树的边为(k,vertexSign[k]),权重为weightSign[k]。函数FindMiniWeight()实现了这个功能

int FindMiniWeight(Mgraph* G,int *wightSign)
{
	int k;
	int min=INFINITY;
	for (int j=0;j<G->numVertexs;j++)
	{
		if (wightSign[j]!=0&&wightSign[j]<min)
		{
			min=wightSign[j];
			k=j;
		}
	}
	return k;
}

下面讲述如何将顶点Vk的信息加入到树中。

  • 首先更新weightSign[k]=0,表示Vk已经在树中了。
  • 从第0个顶点开始,遍历与Vk的距离,比较是与Vk的距离短还是与树的距离短(去掉当前顶点已经在树中的情况)。例如顶点Vm,与树的距离为(m,vertexSign[m]),权重为weightSign[m],比较weightSign[m]与(Vm,Vk)的值。
  • 如果(Vm,Vk)的值较小那么就需要更新数组weightSignvertexSign的值了,将vertexSign[m]的值更新为Vk,表示由于树新加入了顶点Vk,顶点Vm与Vk的距离更短,weightSign[m]更新为(Vm,Vk)的值。
  • 循环遍历所有的顶点,直到所有的顶点与Vk的距离都比较完成。

函数AddTree()实现了下列功能:

void AddTree(Mgraph* G,int* vertexSign,int* wightSign,int vertexNum)
{
	wightSign[vertexNum]=0;
	for (int j=0;j<G->numVertexs;j++)
	{
		if (wightSign[j]!=0&&G->arc[vertexNum][j]<wightSign[j])
		{
			wightSign[j]=G->arc[vertexNum][j];
			vertexSign[j]=vertexNum;
		}
	}

}

首先开始的时候,我们需要选取一个顶点加入树中,比如V0,然后每次循环就寻找一个合适的顶点加入到树中,一共循环N次就把N个顶点全部加入到树中了。下面是代码

void MiniSpanTreePrim(Mgraph *G)
{
	//存放新加入树的结点与树中各节点的距离。
	int *vertexSign=(int*)malloc(sizeof(int)*G->numVertexs);
	if (!vertexSign)
		exit(-1);
	//存放当前树与其他部分的距离。
	int *wightSign=(int*)malloc(sizeof(int)*G->numVertexs);
	if (!wightSign)
		exit(-1);

	int vertexNum; 
	//将V0作为第一个树的节点
	for (int i=0;i<G->numVertexs;i++)
	{
		vertexSign[i]=0;
		wightSign[i]=G->arc[0][i];
	}
	//从已经加入树的顶点开始,每次新加入一个与树的距离最近的顶点,直到所有顶点都加入到树中
	for (int i=1;i<G->numVertexs;i++)
	{
		vertexNum=FindMiniWeight(G,wightSign);
		printf("新加入树的边为:(%d,%d) %d\n",vertexSign[vertexNum],vertexNum,wightSign[vertexNum]);
		AddTree(G,vertexSign,wightSign,vertexNum);
	}
}

注:这是用邻接矩阵实现的,G中 numVertexs是图中顶点的数目,arc是一个二维数组,用 INFINITY表示一个极大的数,模拟∞,可以是10000,arc[i][j]的值表示顶点i和j的边的权值当为 INFINITY表示没有边。参考《大话数据结构》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值