news 2026/4/26 3:14:46

最小生成树的 Kruskal 与 Prim 算法:从连通到最优,一篇文章彻底掌握

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
最小生成树的 Kruskal 与 Prim 算法:从连通到最优,一篇文章彻底掌握

如何用最少的成本,把 n 个城市连接起来?如何铺设光纤、设计电路,既保证连通又成本最低?答案就在最小生成树中。

最小生成树(Minimum Spanning Tree, MST)是图论中至关重要的概念,广泛应用在网络设计、聚类分析、图像分割等领域。而 Kruskal 算法和 Prim 算法正是求解 MST 的两大经典算法。今天,我们就从原理到实践,把它们彻底搞懂。


一、什么是最小生成树?

1.1 定义

无向连通图中,生成树是包含所有顶点的一个无环连通子图。如果图的每条边带有权重,那么最小生成树就是所有生成树中边权总和最小的那一棵。

性质

  • 包含 V 个顶点,恰好 V-1 条边。
  • 无环,且连通。
  • 最小生成树可能不唯一(当存在相同权重的边时)。

1.2 经典场景

  • 设计一个光纤网络,连接 n 个城市,花费最小。
  • 电路板布线,连接所有引脚,总长度最短。
  • 在图中聚类,最小生成树的某些边作为簇间边界。

二、Kruskal 算法——选边法

2.1 核心思想

贪心策略:将所有边按权重从小到大排序,依次选择那些不会形成环的边,直到选中 V-1 条边为止。

“不形成环”的检测依赖并查集(Union-Find)数据结构。

2.2 算法步骤

  1. 对图中所有边按权重升序排序。
  2. 初始化并查集,每个顶点自成一个集合。
  3. 遍历排序后的边(u, v, w)
    • 如果uv不在同一个集合中(即连接它们不会形成环),则选择这条边,并将uv合并。
    • 否则跳过。
  4. 重复步骤 3,直到已选边数 = V-1。

2.3 图解示例

假设有 4 个顶点:A、B、C、D,边的权重:

  • A-B: 1
  • B-C: 3
  • A-D: 4
  • C-D: 2
  • B-D: 5

排序后:A-B(1), C-D(2), B-C(3), A-D(4), B-D(5)。

  • 选 A-B(集合 {A,B})
  • 选 C-D(集合 {C,D})
  • 选 B-C(集合 {A,B,C,D})边数=3,结束。

MST 总权重 = 1+2+3=6。

2.4 复杂度分析

操作复杂度
边排序O(E log E)
并查集合并/查找近乎 O(1)(路径压缩+按秩合并)
总复杂度O(E log E),通常是 O(E log V)

2.5 代码实现(Python)

classUnionFind:def__init__(self,n):self.parent=list(range(n))self.rank=[0]*ndeffind(self,x):ifself.parent[x]!=x:self.parent[x]=self.find(self.parent[x])returnself.parent[x]defunion(self,x,y):rx,ry=self.find(x),self.find(y)ifrx==ry:returnFalseifself.rank[rx]<self.rank[ry]:self.parent[rx]=ryelifself.rank[rx]>self.rank[ry]:self.parent[ry]=rxelse:self.parent[ry]=rx self.rank[rx]+=1returnTruedefkruskal(vertices,edges):""" vertices: 顶点数量 edges: [(u, v, weight), ...] u,v 为顶点索引 """edges.sort(key=lambdae:e[2])uf=UnionFind(vertices)mst=[]total_weight=0foru,v,winedges:ifuf.union(u,v):mst.append((u,v,w))total_weight+=wiflen(mst)==vertices-1:breakreturnmst,total_weight

三、Prim 算法——加点法

3.1 核心思想

贪心策略:从任意一个顶点开始,每次选择连接已选集合与未选集合权重最小的边,将新顶点加入已选集合,直到所有顶点都被覆盖。

这听起来很像 Dijkstra 最短路径算法,但 Prim 维护的是到当前树的最小边权,而非源点的距离。

3.2 算法步骤

  1. 初始化:随机选一个起点s,将其加入集合S
  2. 维护一个数组min_edge或优先队列,记录每个未选顶点到集合S的最小边权。
  3. 每次从优先队列中取出距离最小的顶点v(即最小权重边对应的未选顶点),将该边加入 MST,并标记v加入S
  4. 更新v的邻居到集合S的边权(若比当前记录小)。
  5. 重复直到所有顶点都已加入。

3.3 图解示例

使用上例的图,从 A 开始:

  • S={A},邻接边:A-B(1), A-D(4),选最小 A-B(1),加入 B。
  • S={A,B},新增长边:B-C(3), B-D(5),加上原来的 A-D(4),最小的是 B-C(3)?等一等,C-D(2) 也连接到了 C 和 D,但 C 和 D 都不在 S 中,注意需要保证边一端在 S,一端不在。此时所有跨集合边:A-D(4), B-C(3), B-D(5), 还有 C-D? C 和 D 都不在 S,不跨集合。最小是 B-C(3),加入 C。
  • S={A,B,C},跨集合边:A-D(4), B-D(5), C-D(2),最小 C-D(2),加入 D。

边:A-B(1), B-C(3), C-D(2),权重和=6。

3.4 复杂度分析

实现方式时间复杂度
邻接矩阵 + 遍历O(V²)
二叉堆(优先队列)+ 邻接表O((V+E) log V)
斐波那契堆O(E + V log V)(理论最优)

实际竞赛和工程中,常用堆优化版本。

3.5 代码实现(二叉堆版本)

importheapqdefprim(adj,start=0):""" adj: 邻接表,adj[u] = [(v, weight), ...] start: 起始顶点 返回: mst_edges, total_weight """n=len(adj)visited=[False]*n# 优先队列存储 (weight, u, v) 其中 u 为已选集合中的顶点,v 为未选顶点pq=[]# 初始化:从 start 出发的所有边入队forv,winadj[start]:heapq.heappush(pq,(w,start,v))visited[start]=Truemst=[]total_weight=0whilepqandlen(mst)<n-1:w,u,v=heapq.heappop(pq)ifvisited[v]:continuevisited[v]=Truemst.append((u,v,w))total_weight+=w# 将 v 的邻边中未访问的顶点加入优先队列fornxt,nwinadj[v]:ifnotvisited[nxt]:heapq.heappush(pq,(nw,v,nxt))returnmst,total_weight

四、Kruskal vs Prim 详细对比

维度KruskalPrim
策略按边权全局排序,选边从一点出发,逐渐扩展
数据结构并查集优先队列(堆)
时间复杂度O(E log E)O((V+E) log V)(堆)
适用图稀疏图(E 远小于 V²)效果更好稠密图(E 接近 V²)用邻接矩阵 O(V²) 更快
空间复杂度O(V+E)O(V+E)
对连通性要求整体图必须连通整体图必须连通
实现难度较简单(并查集模板)稍复杂(优先队列维护)
是否易于处理不连通图可生成森林(最小生成森林)只对连通分量有效
典型应用稀疏图,边数量可控,如道路规划稠密图,或需要实时扩展的场景

实际选择建议

  • 如果图是稀疏图(E ≈ V),Kruskal 通常更简单高效。
  • 如果图是稠密图(E ≈ V²),使用 Prim 的邻接矩阵版本(O(V²))优于 Kruskal 的 O(E log V)。
  • 如果图的边需要动态添加且需要维护 MST,Prim 更容易增量更新。

五、扩展:最小生成树的唯一性判断

如果图中所有边的权重互不相同,则最小生成树唯一。否则,可能存在多棵 MST。

判断方法:

  • 应用 Kruskal,在边权相等时,尝试以不同顺序选择,看能否得到不同树。
  • 检查:对于某条权重为 w 的边 e,如果存在一个割,使得 e 是该割中唯一的最小边,则 e 必在某个 MST 中;如果割中有多个等重的最小边,那么 MST 可能不唯一。

六、实际应用场景对比

场景推荐算法理由
城市间铺设电缆(几百个点,边数较少)Kruskal边数可控,排序易
电路板布线(密集引脚)Prim(矩阵版)稠密图,矩阵遍历简单
实时网络拓扑(动态添加节点)Prim(堆)增量扩展方便
处理不连通图(多个孤岛)Kruskal直接得到最小生成森林
大数据图(边超千万)Kruskal(外部排序+并查集)内存友好

七、常见面试问题

Q1:Prim 算法和 Dijkstra 算法的区别?

  • Dijkstra 求的是单源最短路径,累加的是从源点到当前点的路径长度。
  • Prim 求的是 MST,累加的是当前树到新顶点的直接边权。

Q2:如果图不连通,Kruskal 和 Prim 会怎样?

  • Kruskal 会输出最小生成森林(每个连通分量的 MST 合并)。
  • Prim 只从起点开始,只能生成该连通分量内的 MST。

Q3:MST 是否可能含有图中最长的边?

  • 不可能。MST 总是避免使用最长边,除非在环中其他边都更长(不可能,因为环中最长边可以被替换)。具体可用“回路性质”证明。

八、总结

  • Kruskal 算法:全局选边,并查集防环。适合稀疏图。
  • Prim 算法:局部扩展,优先队列取最小跨边。适合稠密图。
  • 两者都是贪心算法,且都能保证全局最优解(贪心选择性质)。
  • 掌握它们,你就掌握了最小生成树的全部基础。

思考题:如果图中存在负权边,Kruskal 和 Prim 还能正确工作吗?为什么?
(提示:最小生成树定义在无向图上,负权边不会导致环形成更小的树,算法依然正确,但一般不考虑负权,因为权值可以是负的,不影响贪心选择)。

如果觉得有帮助,欢迎点赞、收藏、转发~


本文首发于 CSDN,未经授权禁止转载。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/26 3:13:38

WarcraftHelper:魔兽争霸3现代兼容性修复终极教程

WarcraftHelper&#xff1a;魔兽争霸3现代兼容性修复终极教程 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3这款经典游戏在Windows …

作者头像 李华
网站建设 2026/4/26 3:12:02

有限状态机在光纤通道控制器中的高性能实践

1. 有限状态机架构解析&#xff1a;从理论到光纤通道实践 在存储控制器领域&#xff0c;有限状态机&#xff08;Finite State Machine, FSM&#xff09;架构正逐渐成为高性能设计的代名词。这种看似简单的数字电路设计方法&#xff0c;在光纤通道控制器这类对时序和延迟极度敏感…

作者头像 李华
网站建设 2026/4/26 3:08:45

当Parquet文件不再神秘:浏览器里就能轻松查看的数据探索工具

当Parquet文件不再神秘&#xff1a;浏览器里就能轻松查看的数据探索工具 【免费下载链接】parquet-viewer View parquet files online 项目地址: https://gitcode.com/gh_mirrors/pa/parquet-viewer 你是否曾经面对一个Parquet文件感到无从下手&#xff1f;这个专门为大…

作者头像 李华
网站建设 2026/4/26 3:03:21

Claude Ads:基于AI与规则引擎的跨平台广告审计技能实战指南

1. 项目概述&#xff1a;Claude Ads&#xff0c;一个为Claude Code打造的AI广告审计专家 如果你和我一样&#xff0c;在数字营销行业摸爬滚打了十几年&#xff0c;从手动调整Google AdWords关键词出价&#xff0c;到如今管理跨平台、动辄数十个广告账户的复杂预算&#xff0c;…

作者头像 李华
网站建设 2026/4/26 3:00:35

Perseus开源补丁:无需代码修改,解锁《碧蓝航线》全皮肤体验

Perseus开源补丁&#xff1a;无需代码修改&#xff0c;解锁《碧蓝航线》全皮肤体验 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus 还在为《碧蓝航线》中那些精美的限定皮肤无法获取而烦恼吗&#xff1f;…

作者头像 李华
网站建设 2026/4/26 2:59:45

Bouffalo Lab BL616/BL618 RISC-V三模无线MCU解析与应用

1. Bouffalo Lab BL616/BL618 RISC-V MCU深度解析作为一名长期跟踪RISC-V生态发展的嵌入式开发者&#xff0c;当我第一次看到Bouffalo Lab BL616/BL618的规格参数时&#xff0c;确实被这款"三模无线"MCU的配置震撼到了。在IoT设备越来越需要多协议支持的今天&#xf…

作者头像 李华