0

0

c++中如何实现并查集UnionFind_c++并查集路径压缩优化

尼克

尼克

发布时间:2026-01-03 17:30:04

|

827人浏览过

|

来源于php中文网

原创

UnionFind 类核心是用 vector 维护 parent 和 size(或 rank),构造函数初始化 n 个独立集合;find 必须路径压缩,unionSet 需先 find 再按大小/秩合并,避免直接操作非根节点。

c++中如何实现并查集unionfind_c++并查集路径压缩优化

UnionFind 类的基本结构怎么写

并查集核心是维护一组元素的连通性,C++ 中通常用 vector 存父节点索引,下标即元素编号。初始化时每个点自成集合,parent[i] = i。关键操作是 find(找根)和 unionSet(合并),注意函数名别和 C++ 关键字 union 冲突,推荐用 unionSetmerge

常见错误是把 find 写成纯递归但没做路径压缩,或在 unionSet 里直接比较值而非根节点。

  • parentrank(或 size)都建议声明为 private,避免外部误改
  • 构造函数应接受 n 并预分配 parent 大小,避免运行时扩容影响性能
  • 不建议用 map 存非连续编号——除非真有稀疏、动态插入需求,否则纯浪费

路径压缩为什么必须写在 find 里而不是 unionSet 里

路径压缩的本质是:每次 find(x) 时,把从 x 到根路径上所有节点的 parent 直接指向根。它只在查询时生效,且必须“边查边压”,不能攒到合并时再压——因为合并只操作两个根,对中间节点无感知。

典型错误写法是递归 find 里忘了返回压缩后的根,或者用了循环但没更新沿途节点:

立即学习C++免费学习笔记(深入)”;

int find(int x) {
    if (parent[x] != x) {
        parent[x] = find(parent[x]); // ✅ 压缩:先递归到底,再回溯时赋值
    }
    return parent[x];
}

如果写成 return find(parent[x]) 就没压缩;如果用 while 循环但只记了根没改父指针,也白搭。

讯飞绘文
讯飞绘文

讯飞绘文:免费AI写作/AI生成文章

下载

按秩合并(union by rank)和按大小合并(union by size)怎么选

两者都是优化合并策略,控制树高,配合路径压缩后可使单次 find 均摊接近 O(α(n))区别在于:

  • rank 维护的是近似高度,初始化为 0;合并时把 rank 小的树挂到大的下,相等时才给根的 rank +1
  • size 维护子树节点数,合并时把小树挂到大树下,更直观,且后续可支持快速获取连通分量大小

实际中 size 更常用,尤其当需要统计每个集合元素个数时。注意:rank 的“秩”不是真实高度,不能用来判断深度;而 size 是精确值,但不能反映结构平衡性。

示例(按大小合并):

void unionSet(int x, int y) {
    int rootX = find(x), rootY = find(y);
    if (rootX == rootY) return;
    if (size[rootX] < size[rootY]) swap(rootX, rootY);
    parent[rootY] = rootX;
    size[rootX] += size[rootY];
}

容易被忽略的边界和调试陷阱

实际编码时最常踩的坑不在算法逻辑,而在细节处理:

  • 数组越界:parent 下标从 0 开始,但输入点可能从 1 开始编号,记得统一偏移或建 map 映射
  • 未初始化 sizerank:只初始化 parent 不够,size[i] 必须初值为 1,rank[i] 初值为 0
  • 重复调用 find 导致冗余:比如 if (find(a) == find(b)) unionSet(a, b)find 被算两次,应先存根再用
  • 多线程不安全:标准 UnionFind 非线程安全,若需并发访问,得加锁或换用原子操作(但通常并查集用于离线算法,很少真并发)

调试时建议加一个 debugPrint() 打印当前 parentsize,比单步看指针更直观。路径压缩是否生效,一眼就能看出链是否变短。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

715

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

82

2023.09.25

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

122

2023.09.27

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

473

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

135

2025.12.24

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

73

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

25

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

37

2025.11.17

漫画合集pdf网盘入口_漫画解说合集一口气看完
漫画合集pdf网盘入口_漫画解说合集一口气看完

精选高人气漫画合集PDF,一站式网盘入口直达!深度漫画解说整合,一口气看完经典与新作,剧情梳理清晰,省时省力,追漫党必看合集。

3

2026.01.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Rust 教程
Rust 教程

共28课时 | 4.1万人学习

Git 教程
Git 教程

共21课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号