首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >5.4.1 最小生成树(Minimum-Spanning-Tree,MST)

5.4.1 最小生成树(Minimum-Spanning-Tree,MST)

作者头像
week
发布2018-08-24 15:33:24
1.1K0
发布2018-08-24 15:33:24
举报
文章被收录于专栏:用户画像用户画像

一个连通的生成树是图中的极小连通子图,它包括图中的所有顶点,并且只含尽可能少的边。这意味着对于生成树来说,若砍去它的一条边,就会使生成树变成非连通图;若给它添加一条边,就会形成图中的一条回路。

对于一个带权连通无向图G=(V,E),生成树不用,每棵树的权(即树中所有边上的权值之和)也可能不同。设R是G的所有生成树的集合,若T为R中边的权值之和最小的那棵生成树,则T称为G的最小生成树。

最小生成树具有如下性质: 1)最小生成树不是唯一的,即最小生成树的树形不唯一,R中可能有多个最小生成树。当图中的各边权值互不相等时,G的最小生成树是唯一的;

若无向连通图G的边比顶点数小1,即G本身就是一棵树时,G的最小生成树就是它本身。

2)最小生成树的边的权值之和总是唯一的,虽然最小生成树不唯一,但其对应的边的权值之和总是唯一的,而且是最小的。

3)最小生成树的边数为顶点树减一。

构造最小生成树有多个算法,但大多数短发都利用了最小生成树的下列性质:

假设G=(V,E)是一个带权连通无向图,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u含于U,v含于V-U,则必存在一棵包含边(u,v)的最小生成树。

基于该性质的最小生成树算法主要有:Prim算法和Kruskal算法,它们都基于贪心算法的策略,对这两种算法的掌握不应拘泥于其代码实现,而应掌握算法的本质含义和基本思想,并能够模拟算法的实现步骤

GENERIC_MST(G){
	T=NULL;
	WHILE T未形成一棵生成树;
		do 找到一条最小代价边(u,v)并且加入T后不会产生回路;
		T=T并上(u,v);
}

1.普里姆(Prim)算法

prim算法的执行非常类似于寻找图中的最短路径的Dijkstra算法。假设N={V,E}是连通图,Et是N上最小生成树中边的集合。算法从Vt={u0}(u0属于V),Et={}开始,重复执行下述操作:在所有u含于Vt,v含于V-Vt的边(u,v)含于E中找一条代价最小的边(u0,v0)并入集合Et,同时将v0并入Vt,直至Vt=V为止。此时Et中必有n-1条边,则T={Vt,Et}为N的最小生成树。

Prim算法的步骤如下:

初始化:向空树T=(Vt,Et)中添加图G=(V,E)的任一顶点u0,使Vt={u0},Et=空集。

循环(重复下列操作至Vt=V):从图中选择满足{(u,v)|u含于Vt,v含于V-Vt}且具有最小权值的边(u,v),并置Vt=Vt并{v},Et并{(u,v)}

void prim(G,T){
	T=空集;//初始化空树
	U={w};添加任一顶点w
	while((V-U)!=空集){//若树中不含全部顶点
		设(u,v)是使u含于U 与 v含于(V-U)且权值最小的边;
		T=T并{(u,v)};//边归入树
		U=U并{v};//顶点归入树
	}
}

Prim算法的时间复杂度为O(|V|^2),不依赖于|E|,因此它适用于求解边稠密的图的最小树。

2.克鲁斯卡尔(Kruskal)算法

与prime算法从顶点开始扩展最小生成树不同,kruskal算法是一种按权值的递增次序选择合适的边来够着最小生成树的方法。假设N=(V,E)是连通图,对应的最小生成树T=(Vt,Et).Kruskal算法的步骤如下:

初始化:Vt=V,Et=空集。即每个顶点构成一棵独立的树,T此时是一个仅含|V|个顶点的森林;

循环(重复下列操作至T是一棵树):按G的边的权值递增顺序依次从E-Et中选择一条边,如果这条边加入T后不构成回路,则将其加入Et,否则舍弃,直到Et中含有n-1条边。

void Kruskal(V,T){
	T=V;//初始化树T,仅含顶点
	numS=n;不连通分量数
	while(numS>1){//如果不连通分量树大于1
		//从E中取出权值最小的边(v,u)
		if(v和u属于T中不同的连通分量){
			T=T并{(v,u)};//将次边加入生成树
			numS--//不连通分量树减1
		}
	}
}

根据图的相关性质,若一条边连接了两棵不同树中的顶点时,则对这两棵树来说,它必定是连通的,将这条边加入森林中,完成两棵树的合并,直到整个森林合并成一棵树。

在构造过程中,按照网中边的权值从小到大的顺序,不断选取当前未被选取的边集中权值最小的边。依据生成树的概念,n个结点的生成树,有n-1条边,故反复上述过程,直到选取了n-1条边为止,就构成了一棵最小生成树。

通常在krustral算法中,采用堆来存放边的集合,则每次选择最小权值的边只需O(log2|E|)的时间。又生成树T中所有边可以看作一个等价类,每次添加新的边的过程类似于求解等价类的过程。由此可以采用并查集的数据结构来描述T,从而构造T的时间复杂度为O(Elog2 |E|),因此,Kruskal算法适合于变稀疏而顶点较多的图。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年09月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档