并查集:是一种树型的数据结构,时间复杂度近似O(1),用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。其特点是看似不复杂,但数据量极大,使用正常的数据结构会导致占用的空间过大,即使占用空间不成问题,但它的时间复杂度也是极高
常见应用场景:在一些有N个元素的集合应用问题中,通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
基本操作:
- 初始化:在开始将每个元素单独化成一个集合,其集合的标志/代表为元素本身
- 查询:找到查询元素所在的集合的标志/代表
- 合并:将两个集合合在一个大集合,即两个集合的一个集合标志/代表成为另一个集合标志/代表的子结点
基本原理:将每个集合用一棵树来表示。根节点的编号就是整个集合的编号,每个节点都存储它的父节点,例:p[x] 代表的是 x 的父节点
int p[N];//存放节点i的父节点
编写中产生的问题及解决方案:
| 问题编号 | 问题描述 | 解决方案 |
| 问题一 | 如何判断树根 | if ( p[x] == x) |
| 问题二 | 如何求x的集合编号 | while ( p[x] != x){ x = p[x]} |
| 问题三 | 如何合并两个集合 | p[x] = y,y表示另一个集合的树根 |
如何降低时间复杂度?
答:路径压缩,在查询父节点的过程中,当集合中的元素查询过自己的树根后,会将自己以及查询经过元素的父节点都直接指向根节点。
查询代码:
//查找父节点并返回 + 路径压缩
int find(int x){
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
合并代码:
p[find(a)] = find(b);
例题: 合并集合(并查集)

被折叠的 条评论
为什么被折叠?



