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 循环但只记了根没改父指针,也白搭。

九歌
九歌

九歌--人工智能诗歌写作系统

下载

按秩合并(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,比单步看指针更直观。路径压缩是否生效,一眼就能看出链是否变短。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

839

2023.08.22

while的用法
while的用法

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

104

2023.09.25

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

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

129

2023.09.27

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

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

723

2023.08.10

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

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

372

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

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

27

2026.01.21

C++多线程相关合集
C++多线程相关合集

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

27

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

102

2026.02.06

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

3

2026.03.03

热门下载

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

精品课程

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

共4课时 | 22.5万人学习

Rust 教程
Rust 教程

共28课时 | 6.5万人学习

Git 教程
Git 教程

共21课时 | 4万人学习

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

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