最小生成树——Prim算法和Kruskal算法详解

最小生成树

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

 

最小生成树的性质:

  1. 最小生成树不是唯一的。
  2. 最小生成树的边的权值之和总是唯一的
  3. 最小生成树的边数为顶点数减1,即边数=n-1(n为顶点数)

 

下面介绍两种实现最小生成树的算法:

普里姆(Prim)算法

Prim算法的执行非常类似于寻找图的最短路径的Dijkstra算法。

 

基本思想:

对于图G而言,V是所有顶点的集合。现在设置两个新的集合U和T, 其中U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。从所有u∈U,v∈(V−U)u∈U,v∈(V−U) )( V−UV−U 表示除去U的所有顶点)的边中选取权值最小的边(u, v), 将顶点v加入集合U中,将边(u, v)加入集合T中,如此不断重复,知道U = V为止,最小生成树构造完毕,这是集合T中包含了最小生成树的所有边。 (原文链接:https://blog.csdn.net/u011221820/article/details/80476304)

算法步骤如下:

  • 首先在顶点集合中任选其中一点作为起始点,然后寻找当前该点可以访问的所有边,找出其中权重最小的边,并且该顶点未被访问过,将该点加入到已访问顶点集合中,并且将该边加入到最小生成树中,加入后若产生回路则跳过这条边,选择下一个结点,当所有结点都加入到最小生成树中后,就找出了连通图中的最小生成树。
  • 总的来说就是不断地找权值最小并且不产生闭环的n-1。

 

如下图所示就是Prim算法构造最小生成树的过程:

最小生成树——Prim算法和Kruskal算法详解_第1张图片

 

Prim算法的时间复杂度为O(|V|^2),不依赖与|E|,因此它适用于求解边稠密的图的最小生成树,尽管采用其他方法可以改进Prim算法的时间复杂度,但增加了实现的复杂性。

 

克鲁斯卡尔(Kruskal)算法

Kruskal算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。

 

算法思路:

  • 假设一个图有m个顶点,n条边。首先,我们需要把m个顶点看成m个独立的树,并且把n条边按照从小到大的次序进行排列。
  • 按边的权值递增顺序依次从中选出一条边,如果该边加入后不构成回路,则继续运行,否则重新选择另一条边,直到含有n-1条边。

 

如下图所示就是Kruskal算法构造最小生成树的过程:最小生成树——Prim算法和Kruskal算法详解_第2张图片

 

通常在Kruskal算法中,采用堆来存放边的集合,每次选择最小权值的边只需O(log|E|)的时间,又每次添加新的边的过程类似求解等价类的过程,所以可以采用并查集的数据结构来描述,从而时间复杂度为O(|E|log|E|),因此,该算法适合边稀疏而顶点较多的图。

 

总结

Prim算法是以点为对象,挑选与点相连的最短边来构成最小生成树。而Kruskal算法的基本思想是以边为主导地位,始终选择当前可用(所选的边不能构成回路)的最小权植边。

你可能感兴趣的:(数据结构)