【数据结构】图的应用:最小生成树(Prim / Kruskal)

考点频率 :★★★★★(选择题必考,下午题偶尔结合图考查算法选边过程)

难度 :⭐⭐⭐⭐

建议:重点掌握Prim和Kruskal的选边策略差异,能模拟两种算法的执行过程,熟记时间复杂度与适用场景

1️⃣ 什么是最小生成树?

最小生成树(Minimum Spanning Tree,MST) 是图论中的一个核心概念,定义如下:

在一个带权连通无向图 中,选择 n−1n-1n−1 条边,将所有 nnn 个顶点连接起来,使得边的总权值之和最小。这样形成的树称为最小生成树。
打个比方 :你是电信公司的工程师,要在 nnn 个城市之间铺设光缆。城市之间的道路距离(权值)已知。你的任务是用最短的总长度 把 nnn 个城市全部连通------不需要每两个城市都直接连,只要所有城市能互相连通即可(可以经过中间城市)。这个问题的最优解就是最小生成树。

最小生成树的重要性质

  • 一棵有 nnn 个顶点的树,恰好有 n−1n-1n−1 条边
  • 最小生成树不唯一(当存在相同权值的边时,可能有多种方案),但总权值唯一(如果图的边权不全相等,MST可能不唯一)
  • 最小生成树中没有环路(树的基本性质)
  • 任何最小生成树都满足 "切割性质" :对于任意一个顶点集合 SSS,连接 SSS 和 V−SV-SV−S 的最小权值边一定属于某棵最小生成树

求解最小生成树的两种经典算法

  • Prim算法:从顶点出发,逐步"长大"成一棵树(类似"贪心式扩张")
  • Kruskal算法:从边出发,逐步合并森林(类似"贪心式并集")

这两种算法都基于贪心策略,但贪心的对象不同------Prim贪心的是"离当前树最近的顶点",Kruskal贪心的是"当前最小的边"。

2️⃣ Prim算法(从顶点出发,逐步扩张)

2.1 核心思想

Prim算法的策略是:

任意一个顶点 开始,把它看作一棵树的根。然后每次选择一条连接"已选顶点集合"和"未选顶点集合"的权值最小的边 ,把这条边和它连接的新顶点加入树中。重复 n−1n-1n−1 次,直到所有顶点都被包含。
打个比方 :Prim算法像野火蔓延------从一个着火点开始,火势每次向"最近的未燃烧区域"扩散一步,直到整片森林都被点燃。

2.2 算法步骤

  1. 从图中任意选择一个顶点作为起点,加入集合 SSS(已选顶点集合)
  2. 在连接 SSS 与 V−SV-SV−S 的所有边中,选择权值最小 的一条边 (u,v)(u, v)(u,v),其中 u∈Su \in Su∈S,v∈V−Sv \in V-Sv∈V−S
  3. 将 vvv 加入 SSS,将边 (u,v)(u, v)(u,v) 加入最小生成树
  4. 重复步骤2-3,直到 SSS 包含所有顶点(共 n−1n-1n−1 次)

2.3 执行过程示例

:4个顶点,边权如下

  • 1-2: 6, 1-4: 5, 1-3: 1

  • 2-3: 5, 2-4: 3

  • 3-4: 6

    复制代码
        1
      / | \
    1  / |  \ 5
    /   |   \

    3----|----4
    \ | /
    5\ | /3
    |/
    2

从顶点1开始,逐步选择最小边:

步骤 已选顶点集合 SSS 候选边(连接S和V-S) 选择 累计权值
初始 {1} (1-3):1, (1-2):6, (1-4):5 1-3(权1) 1
2 {1, 3} (1-2):6, (1-4):5, (3-2):5, (3-4):6 1-4 (权5)或 3-2(权5) 6
3 {1, 3, 4} (1-2):6, (3-2):5, (4-2):3 4-2(权3) 9

最小生成树总权值 = 1 + 5 + 3 = 9(边集:1-3, 1-4, 4-2)

注意:当有相同权值的候选边时,选哪条都可以,最终总权值相同,但树的形态可能不同。

2.4 Prim算法的复杂度与适用场景

存储方式 时间复杂度 说明
邻接矩阵 O(n2)O(n^2)O(n2) 适合稠密图
邻接表 + 二叉堆 O(elog⁡n)O(e \log n)O(elogn) 适合稀疏图
邻接表 + 斐波那契堆 O(e+nlog⁡n)O(e + n \log n)O(e+nlogn) 理论上最优

适用场景 :Prim算法适合稠密图 (边数多),因为每次选最小边时,用邻接矩阵可以 O(n2)O(n^2)O(n2) 完成,与边数无关。

3️⃣ Kruskal算法(从边出发,逐步合并森林)

3.1 核心思想

Kruskal算法的策略是:

将图中所有边按权值从小到大排序 ,然后从最小的边开始,依次尝试将每条边加入最小生成树 ,如果加入后不形成环路 ,就保留;否则丢弃。重复直到选中 n−1n-1n−1 条边为止。
打个比方 :Kruskal算法像组建联盟------城市之间有许多条可能的连接线路,你从最便宜的线路开始选,只要不会形成"封闭圈子"(环路),就把它纳入计划,直到所有城市都被连通。

3.2 算法步骤

  1. 将图中所有边按权值从小到大排序
  2. 初始化一个森林(每个顶点自成一棵树)
  3. 按排序顺序依次检查每条边:
    • 如果这条边连接的两个顶点不在同一棵树中(加入后不形成环),则加入最小生成树,并合并两棵树
    • 如果两个顶点已经在同一棵树中,则跳过这条边
  4. 重复直到选中 n−1n-1n−1 条边

3.3 执行过程示例

用同样的图(4个顶点,边权如下):

复制代码
边列表(按权值排序):
1-3: 1
2-4: 3
1-4: 5
2-3: 5
1-2: 6
3-4: 6
步骤 当前边 操作 结果
初始 --- 4个顶点各自独立 {1}, {2}, {3}, {4}
1 1-3(权1) 1和3在不同树 → 加入,合并 {1,3}, {2}, {4}
2 2-4(权3) 2和4在不同树 → 加入,合并 {1,3}, {2,4}
3 1-4(权5) 1和4在不同树 → 加入,合并 {1,2,3,4}
4 2-3(权5) 已在同一树 → 跳过 ---
5 1-2(权6) 已在同一树 → 跳过 ---
6 3-4(权6) 已在同一树 → 跳过 ---

选中的边 :1-3(权1),2-4(权3),1-4(权5),总权值 = 9

3.4 Kruskal算法的复杂度与适用场景

关键操作 时间复杂度 说明
边排序 O(elog⁡e)O(e \log e)O(eloge) 主要开销
并查集(判断环路) O(eα(n))O(e \alpha(n))O(eα(n)) 几乎常数

适用场景 :Kruskal算法适合稀疏图 (边数少),因为它的主要开销来自边排序,与边数 eee 的对数成正比。

4️⃣ Prim vs Kruskal(完整对比表,重点!)

对比项 Prim算法 Kruskal算法
策略 从顶点出发,逐步扩张 从边出发,逐步合并
贪心对象 每次选连接已选/未选集合的最小权值边 每次选全局最小权值边,不形成环则加入
数据结构 邻接矩阵 / 优先队列(堆) 并查集(判断环路)
时间复杂度(常用实现) O(n2)O(n^2)O(n2)(邻接矩阵)或 O(elog⁡n)O(e \log n)O(elogn)(堆) O(elog⁡e)O(e \log e)O(eloge)(边排序)
适合图类型 稠密图(边多) 稀疏图(边少)
起始点 需要指定一个起始顶点 不需要起始顶点,直接从边开始
环路判断 天然不会形成环(每次只加一个顶点) 需要用并查集判断是否会形成环
生成树形态 从起点向外"生长" 多个连通分量逐步合并

5️⃣ 经典例题

例题1:对下面的图,用Prim算法从顶点A开始构造最小生成树,写出选边顺序。

复制代码
A ---(4)--- B
| \   / |
|  \ /  |
(2) (3) (1)
|  / \  |
| /   \ |
C ---(5)--- D

解析

  • 从A出发
  • 第1步:A的邻边中最小的是A-C(2)→ 选 A-C
  • 第2步:当前树 {A,C},连接 {A,C} 和 {B,D} 的最小边是C-D(5)还是A-D(3)?→ 选 A-D(权3)
  • 第3步:当前树 {A,C,D},连接 {A,C,D} 和 {B} 的最小边是D-B(1)→ 选 D-B (权1)
    总权值 = 2 + 3 + 1 = 6

答案A-C → A-D → D-B,总权值6


例题2:对同一图,用Kruskal算法构造最小生成树,写出选边顺序。

解析

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

  • 选 D-B(1)
  • 选 A-C(2)
  • 选 A-D(3),检查D在{B,D},A在{A,C},不同树 → 加入
  • 已选3条边,结束

答案D-B → A-C → A-D,总权值6

6️⃣ 记忆口诀

Prim从顶点出发,每次选最近新顶点。

Kruskal从边出发,最小边集合并查。

稠密图Prim,稀疏图Kruskal。

7️⃣ 小测验(评论区对答案)

用Kruskal算法构造最小生成树,边排序后依次加入。在加入第3条边时,需要检查( )。

A. 该边连接的两个顶点是否已经在同一棵树中

B. 该边连接的两个顶点是否都已经被访问过

C. 该边是否与已选边构成回路

D. A和C都正确

🔔 本专栏日更,点击头像 → 专栏《软考中级高频考点》订阅,第一时间接收新内容

#软考中级 #软件设计师 #最小生成树 #Prim #Kruskal #数据结构 #软考备考

相关推荐
一只小小的芙厨2 小时前
前缀和与差分
数据结构·算法
船厂电气自动化ai大模型2 小时前
AI大模型与数学第42课:泰勒级数完整展开(神经网络近似核心)
人工智能·python·深度学习·算法·机器学习
从琳开始9892 小时前
优选算法——双指针(算法原理+力扣题)
算法·leetcode·职场和发展
从琳开始9892 小时前
优选算法——滑动窗口(概念+解题模板+LeetCode例题讲解)
算法·leetcode·职场和发展
Nil2082 小时前
leetcode 94二叉树的中序遍历
算法·leetcode·职场和发展
不会就选b2 小时前
算法日常・每日刷题
算法
一只小小的芙厨3 小时前
最短路总结
数据结构·算法
致Great3 小时前
OpenAI 又把 Codex 往前推了一步: 以后做 Agent,没必要都造一个聊天框
算法
Shell运维手记3 小时前
Linux (挂载|rpm|yum|源码编译)
linux·运维·笔记·网络协议·bash
2kπ4 小时前
QT开发笔记
开发语言·笔记·qt