V

算法可视化

ZHEN
分享到微博分享到 XGitHub 仓库个人主页
学习工具算法复杂度速查算法学习路径
数据结构数组链表栈队列树堆哈希表图字典树并查集LRU 缓存跳表线段树B+ 树布隆过滤器树状数组
经典排序算法冒泡排序鸡尾酒排序双调排序选择排序插入排序二分插入排序希尔排序归并排序自顶向下归并快速排序三路快排双轴快排堆排序计数排序基数排序桶排序
图算法Dijkstra 最短路Kruskal 最小生成树Prim 最小生成树Bellman-Ford 最短路拓扑排序Floyd 多源最短路强连通分量2-SAT最大流二分图匹配LCA 倍增欧拉路径
动态规划编辑距离0-1 背包完全背包最长公共子序列最长递增子序列硬币找零方案数石子合并旅行商 TSP树形 DP数位 DP换根 DP
回溯与搜索N 皇后子集生成全排列组合总和迷宫寻路岛屿数量单词搜索数独A* 寻路
字符串KMP 字符串匹配Rabin-KarpBoyer-MooreManacher后缀数组LCP / height 数组AC 自动机Z 函数
数学与数论埃氏筛线性筛欧几里得算法快速幂扩展欧几里得中国剩余定理欧拉函数米勒-拉宾FFTPollard's Rho
计算几何凸包旋转卡壳最近点对线段相交扫描线求交
查找二分查找二分边界旋转数组搜索二分答案三分查找

Kruskal 最小生成树

图算法 · 最小生成树(MST)

什么是最小生成树

在一张无向带权连通图里,选出若干条边把所有点连起来、不成环、且总权重最小——这就是最小生成树(MST)。比如要给几个村庄铺电缆,怎么连最省料?

Kruskal 怎么做

把所有边按权重从小到大排序,依次考虑每条边:用并查集判断这条边的两端是否已经连通——没连通就加入生成树(并把两端合并到一组),已连通就跳过(再加它会成环)。选够 V−1 条边就完成。

下面固定一张 6 个点的无向带权图。点「下一步」按权重从小到大逐条考虑:当前边黄色高亮——不成环就加入(变绿)、两端点也连进森林;已连通就成环跳过(灰虚线)。走到底得到 5 条边、总权重最小的生成树。右侧代码随每一步同步高亮。

123456789ABCDEF

9 条边按权从小到大排好;MST 空、每个点自成一组

1function kruskal(edges: [number, number, number][], n: number): number {
2 edges.sort((a, b) => a[2] - b[2]);
3 const parent = Array.from({ length: n }, (_, i) => i);
4 const find = (x: number): number => {
5 while (parent[x] !== x) x = parent[x];
6 return x;
7 };
8 let weight = 0;
9 for (const [u, v, w] of edges) {
10 const ru = find(u), rv = find(v);
11 if (ru === rv) continue;
12 parent[ru] = rv;
13 weight += w;
14 }
15 return weight;
16}
边数 E9
当前边-
MST 边数0/5
MST 权重0
成环跳过0
1 / 20

为什么「每次贪心取不成环的最小边」是对的?由切分定理保证:横跨任意一种分割的最小边,一定属于某棵最小生成树。判环用并查集,几乎是常数时间;整体复杂度由排序主导,约 O(E log E)。判环正是并查集的经典应用。

Kruskal 在哪里用

最省布线:电网 / 网络 / 道路连通所有节点、总成本最低。
聚类:建 MST 后切掉最大的几条边,自然分成簇。
近似算法基础(如旅行商问题的近似)。另一种 MST 算法是 Prim(从点集生长)。

它把「贪心 + 并查集」用得很漂亮——想复习并查集怎么合并、找根,可回看 数据结构 · 并查集。