生成树和最小生成树

  树:在图中,常常将树定义为一个无回路连通的无向图。只选定图中某个顶点做根,以树根为起点对每条边定向,就能将他们变成通常的树。树中悬挂的顶点称为树叶,其他顶点称为分支点,一个非连通图,如果它的各个连通分量都是树,则这种非连通图称为森林。树是森林的特殊情况,树中无回路,因此树中必然没有自身环也无重边,否则就出现回路不是树了。

  生成树和生成森林:

  生成树:连通图的一个子图如果是一棵包含所有顶点的树,则该子图称为图的生成树。由于n个顶点的连通图至少有n-1条边,而所包含n-1条边及n个顶点的连通图都是无回路的树,所以生成树是连通图的极小连通图。所谓极小是指边数最小,若在生成树中去掉任何一条边,都会使之变为非连通图,若在生成树上任意添加一条边,就必定出现回路。DFS是图的深度搜索得到的生成树称为深度优先生成树。BFS图的广度搜索得到的生成树称为广度优先生成树。

  生成森林:非连通的无向图,则要若干次从外部调用DFS(BFS)算法,才能完成对图的遍历,每一次外部调用,只能访问到图的一个连通分量的顶点集,这些顶点和遍历时所经过的边构成了连通分量的一棵DFS(BFS)生成树。图的各个连通分量的DFS(BFS)组成了DFS(BFS)生成森林。类似的,若图是非强连通的有向图,且初始出发点又不是有向图的根,则遍历时一般也只能得到该有向图的生成森铃。

   最小生成树:图的生成树不是唯一的,从不同的顶点出发进行遍历,可以得到不同的生成树。对于连通网络,边是带权的,因而图的生成树的各边也是带权的。我们把生成树的权值总和称为生成树的权,并把权最小的生成树称为图的最小生成树。

   最小生成树算法:

     构造最小生成树应遵循以下规则:
(1)只能使用原图中的边来构造最小生成树
(2)只能使用且仅使用n-1条边来连接图中n个顶点。
(3)所有产生回路的边均不得使用

      普利姆算法:假设G=(V,E)是连通网络,即V={1,2,....n}。设所求的最小生成树为T = (U,TE),其中U是T的顶点集,TE是T的边集。并且将G中边上的权看做是长度。
基本思想:
(1)开始的时候U={v0}(v0属于V),TE={};
(2)在所有u属于U,v属于V-U的边(u-v)属于E中,找出一条权值最小的边(u0,v0)并入集合TE,同时将v0并入集合U;
(3)重复执行b操作:直至U=V,此时TE必有n-1条边,则T=(U,TE)是G的一棵最小生成树。

 

template<class T>
void AdjMatrixGraph<T>::MinSpanTree_prim(Edge *mst)  //构造带权图最小生成树的普里姆算法
{
  int n = vertcount,i,j;
  for(i = 0;i<n-1;i++)
  {
	  Edge e= {0,i+1,dajmatrix[0][i+1]};
	  mst[i] = e;
  }
  cout<<"mst数组初值:"<<print(mst,n-1);
  for(i = 0;i<n-1;i++)
  {
     int minweight = MAX_WEIGHT;
	 int main = i;
	 for(j = i;j<n-1;j++)   //寻找当前最小权值的边的顶点
		 if(mst[j].weight<minweight)
		 {
		    minweight = mst[j].weight;    //更新最小权值
			min = j;  //保存当前最小权值边的终点序号
		 }
		 Edge temp = mst[i];  //交换最小权值的边
		 mst [i] = mst[min];
		 mst [min] = temp;
		 int u = mst[i].dest;  //刚并入u的顶点
		 for(j = i+1;j<n-1;j++)  //调整mst[i+1]及其后元素为权值最小的边
		 {
			 int v = mst[j].dest;  //原边在v-u中的终点
			 if(adjmatrix[u][v]<mst[j].weight)  //若有权值更小的边(u,v)边替换原边
			 {
			 mst[j].weight = adjmatrix[u][v];
			 mst[j].start = u;
			 }
		 }
		 cout<<"\nast 数组:";  print(mst,n-1);
  }
}

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值