天天看点

Kruscal算法求图的最小生成树

  和Prim算法求图的最小生成树一样,Kruscal算法求最小生成树也用到了贪心的思想,只不过前者是贪心地选择点,后者是贪心地选择边。而且在算法的实现中,我们还用用到了并查集(也称不相交集的)Union /Find 算法来判断两个节点连通后会不会形成一个环。该算法的思想很简单:将图的所有边按从小到大顺序排序,每次都选取权值最小的边加入最小生成树,如果该边的加入会使生成树形成一个环,则跳过该边。

  这里引入并查集的概念,可以使问题变得简单化。并查集就是利用一个数组sets,如果sets[a]=b,那么我们说a和b在一个生成树(集合)中,且a的双亲是b,如果sets[a]=a,那么我们说a是一个生成树的根。一个图的最小生成树在还没有完全生成前,可能存在多个互不连通的生成树,他们是不相交的集合,我们需要把这些不同的生成树连通起来。

 于是,通过定义一个findroot函数,我们可以找到某顶点的双亲,然后找到该顶点的双亲的双亲,最终找到顶点所在最小生成树的根,例如:如果我们知道sets[a]=b,sets[b]=c,sets[c]=c,那我们可以说a、b、c在同一棵生成树(集合)里,且所在最小生成树的根为c。假设另一个不相交的生成树的根为d,如果我们令sets[c]=d,则将这两个生成树合并为了一个大的生成树,其根为d。

1.创建一个9条边,6个顶点的带权无向连通图。

Kruscal算法求图的最小生成树

初始状态的并查集如下:

Kruscal算法求图的最小生成树

2.将图所有边按权值进行排序。选择权值最小的一条边的两个邻点。为了避免混乱,统一约定该边右边的邻点加入左边的邻点的并查集中,在图中表示为2顶点挂在1顶点下面。

Kruscal算法求图的最小生成树
Kruscal算法求图的最小生成树

3.就这样,按照权值从小到大不断遍历所有边,都统一把边的大序号的邻点加入小序号的邻点所在的生成树中,3顶点挂在2顶点下面,4顶点挂在3顶点下面,5顶点挂在4顶点下面,6顶点挂在2顶点的下面,最终最小生成树不断长大,且最后所有顶点本质上都挂在1顶点下面,即最小生成树的根为1顶点。

Kruscal算法求图的最小生成树
Kruscal算法求图的最小生成树

4.最好还剩4条边没有遍历。但我们发现,这4条边的两个邻点都在同一个生成树中了,即他们findroot的结果都是1。如果我们把任意一条边的两个邻点连接起来,都会形成一个环,这是不允许的。故最小生成树的生成就此结束。

1.引入头文件,和之前所讲的的其他图论算法不同的是,这里单独定义一个表示图的边的类,用u,v记录边的邻接点,w记录边的权值。

2.定义表示图的类

3.这里自定义一个排序比较函数,后面给储存边的容器排序时会用到。

4.Graph类的构造函数以及析构函数

5.Kruscal算法的实现。

6.寻根函数的实现

7.对顶点按照权值排序函数的实现

8.测试部分。定义一个6个顶点9条边的图,调用接口求该图的最小生成树

控制台输出结果:

Kruscal算法求图的最小生成树

数学是符号的艺术,音乐是上界的语言。