最小生成树的构造

最小生成树

树也是图的一个特例

什么是生成树?

连通图的生成树是包含全部顶点的一个极小连通子图,即此树包含图中所有的顶点,并且只含尽可能少的边,此树还是连通
一个图的生成树不只一个,权(各边权值之和)最小的生成树则为此图最小生成树
最小生成树具有以下特性:
1、最小生成树形状不唯一,但最小生成树权是唯一的。且为所有生成树中最小的
2、最小生成树边数为顶点数减1
3、若无向连通图边数比顶点数少1,图本身就是一棵树,则最小生成树是它本身

最小生成树的构造

构造最小生成树都利用最小生成树的同一性质:MST性质
假设N=(V,{E})是一个连通网,U是顶点集V的一个非空子集,如果(u,v)是一条具有最小权值的边,其中u属于U,v属于V-U,则必定存在一颗包含边(u,v)的最小生成树
先看下面的两个算法,结合理解
大体的意思理解为:首先树T为空,在还没有变成一棵生成树之前,一直找一条权值最小的边加入T,并且T不会产生回路。

普里姆(Prim)算法

首先就是从图中的一个起点a开始,把a加入U集合,然后,寻找从与a有关联的边中,权重最小的那条边并且该边的终点b在顶点集合V-U中,我们也把b加入到集合U中,并且输出边(a,b)的信息,这样我们的集合U就有:{a,b},然后,我们寻找与a关联和b关联的边中,权重最小的那条边并且该边的终点在集合:(V-U)中,我们把c加入到集合U中,并且输出对应的那条边的信息,这样我们的集合U就有:{a,b,c}这三个元素了,一次类推,直到所有顶点都加入到了集合U。
如下图例:这样就找到了图a的一棵最小生成树f
在这里插入图片描述
简单伪代码实现如下:
void Prim(G,T)
{
T=NULL; //初始化空树
U={w}; // 添加任意顶点
while((V-U)!=NULL) //树中不含全部顶点即还不是生成树
{
T=T+(u,v); //将权值最小的边加入树中
U=U+{v}; //顶点归入集合U中
}
}

克鲁斯卡尔(Kruskal)算法

Kruskal算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法
算法思路:
(1)将图中的所有边都去掉。
(2)将边按权值从小到大的顺序添加到图中,保证添加的过程中不会形成环
(3)重复上一步直到连接所有顶点,此时就生成了最小生成树。这是一种贪心策略。
在这里插入图片描述 Kruskal算法伪代码实现: void Kruskal(V,T) { T=V; //初始化树T,仅含顶点,也可以说仅含根结点的森林 numS=n; //连通分量数 while(numS>1) { if((u,v)属于不同的连通分量) { T=T+(u,v); //将权值最小的边加入生成树中 numS–; } } }