图的邻接矩阵存储方式之普里姆prim算法(最小生成树问题)

假设在n个城市间建立通信网络,则联通n个城市只需要n-1条线路,这就存在n!种联通网络即生成树,那么这就要考虑怎么建立网络能使路径最短,成本最低或是权重和最小,这个问题就是最小生成树问题(minimum cost spanning tree)。而prim算法是构造最小生成树的方法之一。

为了实现这个算法,需要设置一个辅助数组closedg[i],其中有两个分量,一个存储顶点元素(边的起始点),一个存储权值,本质上,这个数组存储的是已经进入最小生成树的顶点其他顶点最小权重信息,包括边的起始点,例如,closedg[k]=(v1,8),代表生成树中点v1到下标为k的元素的权重最小,且最小权重为8。

代码实现过程:

1,定义数组辅助结构体数组,通过首先放入一个顶点下标为k的顶点,初始化数组,并令close[k]={ (随机数) , 0}

2,选出最小路径下标k顶点,辅助数组中存储的顶点是最小路径边的起始点,终点是k号顶点,同时计算最小代价:

        weightsum = weightsum + closedg[k].weight;             //计算最小代价值

3,更新辅助数组,有了新的顶点加入到生成树中,要保证辅助数组中存储的是到剩余顶点的最小路径。循环执行2和3步n-1次。

具体代码如下:(此代码是建立再邻接表存储结构之上的,关于邻接表的实现代码请参考之前博客)

//////////////////////////////////////pirm算法////////////////////////////
int prim_algorithm(DGraph G,Vertex_type ch)
{
    typedef  struct  
	{
		Vertex_type vex;
		int weight;
	}Auxiliary[VERTEX_NUM];
	Auxiliary closedg;         //辅助数组

	int weightsum = 0;
	//////////////////////辅助数组初始化////////////////////////////假设从k号顶点开始
	int k = local_vex(&G,ch);
	for (int i = 0; i < G.vex_num; i++)
	{
		if (i!=k)
		{
			closedg[i].vex = G.vex[k];
			closedg[i].weight = G.arc[k][i];
		}
	}
	closedg[k].weight = 0;
	////////////////////////////////////////////////////////////////


	for (int i = 0; i < G.vex_num-1; i++)                    //剩余的vex_num-1个顶点
	{
		int min = INFINITY;
		////////////////////////////选出最小的路径///////////////////
		for (int j = 0; j < G.vex_num; j++)
		{
			if (closedg[j].weight!=0&& closedg[j].weight

算法分析:初始化部分的循环语句频度为n,第二个循环频度为n-1,其中有两个循环,一是求最小权重,其频度为n,二是更新辅助数组,其频度为n,由此可知普里姆算法的时间复杂度为O(n^2),与边数无关,因此适合稠密的网(边数多,顶点少)的最小生成树。

你可能感兴趣的:(图的邻接矩阵存储方式之普里姆prim算法(最小生成树问题))