数据结构——二十二、并查集(王道408)

文章目录

前言

本文介绍了并查集(Disjoint Set)的逻辑结构、存储实现和优化方法。主要内容包括:1)用互不相交的树表示集合,通过查操作(Find)和并操作(Union)实现集合操作;2)使用双亲表示法存储结构,给出初始化、查、并的代码实现;3)提出优化方案,通过小树合并到大树的方式控制树高,将查操作的时间复杂度从O(n)优化到O(log₂n)。并查集是一种高效处理不相交集合的数据结构,适用于需要频繁查询和合并集合的场景。文章还总结了并查集的重要考点和知识点框架。
代码在文章开头,有需要自取🧐

一.逻辑结构------"集合"

1.全集

2.子集与森林

  • 将各个元素划分为若干个互不相交的子集

  • 森林。森林是m(m≥0)棵互不相交的树的集合

  • 同一子集中的各个元素,组织成一棵树用于表示各个子集之间互不相交的关系

二.用互不相交的树,表示多个"集合"

1.查操作

如何"查"到一个元素到底属于哪一个集合?

答:从指定元素出发,一直寻找它的父结点,直至找到根节点,根节点代表了其属于哪一棵树
如何判断两个元素是否属于同一个集合?

答:分别查到两个元素的根,判断根节点是否相同即可

2.并操作

如何把两个集合"并"为一个集合?

答:让一棵树成为另一棵树的子树即可
注:并查集(Disjoint Set)是逻辑结构------集合的一种具体实现,只进行"并"和"查"两种基本操作

三.代码实现并查集

1.存储结构------双亲表示法

1.定义

2.代码

c 复制代码
#define SIZE 13
int UFSets[SIZE];	//集合元素数组

3.图例

2.初始化

初始状态:所有的元素都是一个一个独立的结点

c 复制代码
//初始化并查集
void Initial(int S[]){
	for(int i=0; i<SIZE; i++)
		S[i]=-1;
}

3.查操作

1.定义

  • Find--"查"操作:确定一个指定元素所属集合

2.代码

c 复制代码
//Find"查"操作,找x所属集合(返回x所属根结点)
//x表示这个元素的数组下标
int Find(int S[], int x){
	while(S[x]>=0)//循环寻找x的根
		x=S[x];
	return x; //根的S[]小于0
}

3.时间复杂度

4.并操作

1.定义

  • Union--"并"操作:将两个不相交的集合合并为一个

2.代码

c 复制代码
}
//Union"并"操作,将两个集合合并为一个
//Root1和Root2是要合并的两个集合的根结点
void Union(int S[], int Root1, int Root2){
	//要求Root1与Root2是不同的集合
	if(Root1==Root2) return;
	//将根Root2连接到另一根Root1下面
	S[Root2]=Root1;
}

3.时间复杂度

四.使用Union操作优化并查集

可以看出查这个操作的最坏的时间开销直接和树的高度的相关,如果我们想要优化这个并查集的效率的话,那我们能否在构造这个树的时候让这棵树别长得太高

1.优化思路

  • 在每次Union操作构建树的时候,尽可能让树不长高

    ①用根节点的绝对值表示树的结点总数

    ②Union操作,让小树合并到大树

  • 例子

    • A这棵树有6个结点,因此存为-6
    • C这棵树有2个结点,因此存为-2
    • C这棵树有5个结点,因此存为-5

2.代码展示

c 复制代码
//Union"并"操作,小树合并到大树
void Union(int S[], int Root1, int Root2){
	if(Root1==Root2) return;
	if(S[Root2]>S[Root1]){//Root2结点数更少
		S[Root1] += S[Root2]; //累加结点总数
		S[Root2]=Root1; //小树合并到大树
	}else{
		S[Root2] += S[Root1]; //累加结点总数
		S[Root1]=Root2; //小树合并到大树
	}
}

3.优化后影响

  • 该方法构造的树高不超过 ⌊ l o g 2 n ⌋ + 1 \lfloor log₂n\rfloor+1 ⌊log2n⌋+1
  • Union操作优化后,Find操作最坏时间复杂度:O(log₂n)

五.知识回顾与重要考点

结语

二更😉
想要查看更多章节?请点击一、数据结构专栏导航页

相关推荐
二十三之歌3 小时前
Redis 中文学习手册
数据库·redis·学习
青衫码上行3 小时前
【从0开始学习Java | 第21篇】网络编程综合练习
java·网络·学习
web安全工具库3 小时前
告别刀耕火种:用 Makefile 自动化 C 语言项目编译
linux·运维·c语言·开发语言·数据库·算法·自动化
失心疯_20234 小时前
PyQt开发_小学学习辅助工具
学习·pyqt
我的xiaodoujiao4 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 18--测试框架Pytest基础 2--插件和参数化
python·学习·测试工具·pytest
今天只学一颗糖4 小时前
Linux学习笔记--GPIO控制器驱动
笔记·学习
yuxb734 小时前
Ceph 分布式存储学习笔记(四):文件系统存储管理
笔记·ceph·学习
ouliten4 小时前
cuda编程笔记(29)-- CUDA Graph
笔记·深度学习·cuda
Larry_Yanan4 小时前
QML学习笔记(四十一)QML的ColorDialog和FontDialog
笔记·学习