Q: minimum spanning tree 的定义
A: 给定一幅图G = (V,E), 找到E的一个能够连接起G中所有的节点(vertices)的边子集T, 并且边子集的权重之和最小, 这就是我们所说的最小生成树。
由于T是无环的, 并且联通所有的节点, 所以T然是一棵树。 我们称T为图G的 minimum spanning tree。
上图(graph)的minimum spanning tree(即T) 为:
所以现在问题是 , 给定一个具有weighted edges 的graph G, 找到G的最小生成树T。
解决这个问题的有两个算法。 一个是prim's algorithm, 以前的博客已经介绍到。 还有一个算法是Kruskal Algorithm 来找到图G的minimum spanning tree.下面主要介绍Kruskal‘s algorithm.
Kruskal's algorithm 使用到了disjoint-set 的概念。算法伪代码如下:
下面对于上述图, 使用Kruskal's algorithm 的运算过程。
由于Disjoint set 具有2 个重要的operations, 即Find 和 Union, Kruskal‘s algorithm 利用了Disjoint-set 的知识。 Find 的作用是take an item, 返回的是代表这个 item 所在集合的代表。
Union take 2 disjoint-set, and merge them into one disjoint set。
根据上面的伪代码, 下面给出解释。
首先, 集合A存储是是MST(最小生成树)的边的集合。 所以initially, A 被初始化为空集∅。 eventually, Kruskal’s Algorithm 返回的也是A(此时A中含有MST的所有的边)。
然后, 对于图中的每一个vertex, 我们都创建 具有一个元素的Disjoint-set(single vertex Disjoint set)。
然后对于图中的所有边E, 按照边权重, 对其按照从小到达的顺序排序。 所以, 对于上图, edge with the smallest weight will be in the front , 此例子中, 权重最小的边为1的那个. 具有最大权重的边在最后(为6)等等。
接下来, 从排好序的边集合中选择边。 当然, 首先选择排在最前面的边, 即1。 等等。
如果这个边的两个顶点v1 和v2 不再同一个Disjoint-set 中, 我们就push that edge into A, and then merge the two disjoint-set(ie, v1, v2) into one。
循环完成之后, 最终返回A。
现在讨论分析下图运用Kruskal‘s algorithm 的算法 如下。
step1: 选中具有最小权重的边(当然1(即(c, f)边)在最前面), 即为连接c和f 的边。 由于c和f 属于不同的Disjoint-set, 所以我们merge them, and then push the edge into A:
step2: 下一个具有权重为2的边, 例如先选中a f。 由于二者属于不同的Disjoint-set, 所以我们merge them, and then push the edge into A:
等等, 依次类推, 有如下各个图:
step3:
step4:
step5:
接下来, 假如说首先选中边e, f(权重为4), 但是由于e, f 属于同一个Disjoint-set, 所以we will not push this edge in to A。
step6:
最终, 我们得到个这个图的MST(当然具有minimum weight)。
代码见下个博客。