最小生成树之Kruskal算法,其核心原理也是切分定理
切分定理:
切分
把图中的节点分为两部分,称为一个切分(Cut);
横切边
如果一个边的两个端点,属于切分(Cut)不同的两边,这个边称为横切边(Crossing Edge);
切分定理
给定任意切分,横切边中权值最小的边必然属于最小生成树;
Kruskal算法属于切分定理的逆向应用。
首先将所有的边按从小到大进行排序。
选出最短的边。
此时最短的边为{0,1}这条边,此时把{0}和{2}看成一个切分,{0,1}这条是横切边且最短,所以将这条加入到最小生成树边中。此时图变为
然后再找出次短边,因为对边进行排过序,现在只需要O(1)的时间,
此时找到边是{3,4},此时的切分为{3},{4},这条边是横切边中最短的(虽然只有一条),那么一定是最小生成树中的边,将其加入最小生成树中,此时的图为
按此算法找到下一条边是{4,5},此时的切分为{3,4}和{5},{4,5}这条边仍为最小横切边,将其加入到最小生成树中。此时图跟新为
在找下一条边是{2,3},那么此时的切分为{0,2}和{3,4,5},发现这个切分出现了两条横切边{2,3}和{2,4},虽然他们长度相等,那么我们任意选择一条{2,3}作为最短横切边。此时将{2,3}加入到最小生成树中去。那么此时的图可以更新为
可以看到在最小生成树的内部,还有一条边{2,4},这条边在树的内部构成了环,这就不符合树的要求了。我们现在可以暂时不管他,因为我们对所有的边进行了排序,一定会对所有的边进行遍历,到时候遍历到它的时候在进行处理。
继续遍历下一条边,恰巧是刚刚那条有问题的边{2,4},这条边造成的问题是使得这个图内构成了环。所以这条边需要被舍弃,那么引伸出一个问题,那就是环检测,在学习BFS或者DFS时,我们知道遍历一个图可以检测这个图内是否有环,很明显如果使用BFS或者DFS时间复杂度太高,所以我们使用并查集这个高级数据结构,可以快速判断一图中是否有环。所以我们在每操作一条边的时候都要判断这条边都否构成了环,按照这个算法直到所有顶点都被加入到最小生成树了。
下面是代码实现Kruskal算法。