交互式图论学习
交互式图论学习
Guest User
Using app without sign in
最小生成树计算器
通过排序边和使用并查集找到最小生成树
选择算法并生成步骤以开始可视化
Kruskal 算法按权重递增考虑各边,加入每条不会形成环的边,从而找到最小生成树。与 Prim 生长单棵树的方式不同,Kruskal 生长由多个分量组成的森林,这些分量逐渐合并为一棵树。
在按权重排序所有边后,算法从最小的边开始遍历。对每条边,它用并查集(不相交集)结构以近乎常数的时间检查两端点是否已在同一分量。若不在,则接受该边并合并分量;否则作为成环边跳过。排序主导开销,运行时间为 O(E log E)。
Kruskal 算法更适合稀疏图以及边已预先排序的问题,如单链接聚类、图像分割和按成本分级的网络设计。内嵌的并查集结构本身就是热门面试题,涵盖路径压缩和按秩合并。
把所有边按权重排序,然后依次扫过这个列表,凡是连接两个不同连通分量的边就加入。并查集让「是否属于不同分量」这一判断几乎不花代价,这是整个算法高效的关键。
Kruskal(图):
把所有边按权重升序排序
对每个结点 v 执行 建立集合(v)
mst = []
按排序顺序对每条边 (u, v, w):
若 查找(u) != 查找(v): // 属于不同分量
合并(u, v)
mst.追加((u, v, w))
若 mst 已有 V - 1 条边: 退出
返回 mstKruskal 生长的是森林而非树。若干互不相连的片段各自独立发展,并在便宜的边把它们连起来时逐步合并,这正是它与 Prim 的结构性差异,也是 Kruskal 能免费处理非连通图的原因:它直接返回一片最小生成森林。其正确性同样来自把割性质应用到各分量的边界上,与 Prim 完全一致。
在与 Prim 示例完全相同的图上构造最小生成树,以便在同一组数据上比较两者的发现顺序。
示例图: 无向边 A-B (2)、A-C (3)、B-C (1)、C-D (4) 和 B-D (7)。
最小生成树由 B-C、A-B 和 C-D 构成,总权重为 1 + 2 + 4 = 7,与 Prim 从 A 出发得到的结果完全一致。在边权互不相同的情况下两棵树必然相同,但发现顺序不同:Prim 依次取 A-B、B-C、C-D,从 A 向外生长;Kruskal 则按纯粹的权重顺序取 B-C、A-B、C-D,并在途中显式拒绝了一条会成环的边。这种顺序上的差别在可视化工具中一目了然,也是理解两个算法真正区别的最佳途径。
时间: O(E log E) · 空间: O(V + E)
对边排序的代价 O(E log E) 支配了其余一切,而由于 E 至多为 V 的平方,log E 与 log V 只差常数因子,因此它等同于 O(E log V)。排序之后,循环至多执行 2E 次查找和 V - 1 次合并。在同时采用路径压缩与按秩合并时,每次操作的代价是 V 的反阿克曼函数,对任何能装入内存的输入都小于 5,可以按常数看待。因此并查集部分实际上是 O(E),排序构成了全部开销。当边本身已经有序,或因权重是较小整数而可以用桶排序时,Kruskal 会降到接近线性,并明显优于 Prim。
Kruskal 与 Prim 解决的是同一个问题。稠密程度、边的顺序以及连通性决定了哪一个更合适。
| 替代算法 | 以下情况更合适 | 代价 |
|---|---|---|
| Prim 算法 | E 接近 V 的平方的稠密图,此时把所有边排序是一种浪费。 | O(E log V) 或 O(V^2) |
| Boruvka 算法 | 你想并行化。每个分量同时选出自己最便宜的出边。 | O(E log V) |
| 配合桶排序的 Kruskal | 权重是较小整数,排序变为线性,整体也接近线性。 | O(E·α(V)) |
| 最小生成森林 | 图不连通。Kruskal 无需任何修改即可胜任。 | O(E log E) |
阅读完整文章: Minimum Spanning Trees: Prim, Kruskal and Boruvka
相关算法: 普里姆最小生成树算法, 博鲁夫卡算法, 环检测