数据结构(九)---并查集

embedded/2024/9/26 1:24:08/

目录

1.集合

2.集合的相关操作

(1)查(Find):

•Find操作的优化

(2)并(Union):

•Union操作的优化


1.集合

数据元素之间的逻辑关系可以为集合,树形关系,线性关系,图关系。对于集合而言,一个集合可以划分为若干个互不相交的子集。在集合下,两个元素之间的关系只有两种,即从属于同一个子集或从属于不同子集。

那么怎么表示这样的关系呢?在讲解森林时,提到过森林的概念,即互不相交的树的集合,那么在这里,我们可以把不同子集的元素放到不同的树中表示。

2.集合的相关操作

并查集(Disjoint Set)是逻辑结构,也就是对集合的一种具体实现,只进行“并”和“查”两种基本操作。

(1)查(Find):

•要想找到某一个元素属于哪一个集合,可以从指定元素出发,一路向上找到其唯一对应的根节点(有几个根节点,就有几棵树,就有几个集合)

在树的存储结构中,我们讲了双亲表示法,孩子表示法,孩子兄弟表示法,用哪种方法表示集合比较合适呢?

因为在集合中,需要向上找到根节点,显然使用双亲表示法更加方便。即,用一个静态数组,就能表示出父子的关系。忘记了可以看看:树

例如下图,元素L的数组下标是11,其父节点为数组下标为4的元素,即E,如此推上去,直到推到数组下标为0的元素,就是根节点了。

① 初始化并查集,将各个元素初始化为各自独立的子集。

#define SIZE 13
int UFSets[SIZE];    //集合元素数组//初始化并查集
void Initial(int s[]){for(int i=0;i<SIZE;i++)s[i]=-1;
}

② 查操作

// Find 操作,找 x 所属集合(返回 x 所属根结点)
int Find(int s[], int x) {while (s[x] >= 0)x = s[x];    // 循环寻找 x 的根return x;    // 返回根节点的下标
} 

时间复杂度:

对于下图,如果想查找J元素所属的集合,只需要向上找一次就可以找到根节点。

但是对于下图,就需要向上找很多层,才能找到根节点。

所以,若节点数为n,Find最坏时间复杂度为O(n),可以看到Find最坏时间复杂度与高度h直接相关,所以优化并查集的效率时,可以在合并树时减小树的高度。这一点留到“合并树”的时候讲。

•如果想判断两个元素是否属于同一个集合,那就分别查找两个元素的根节点,判断根节点是否相同。

bool Compare(int Root1, int Root2) {if (Find(Root1) == Find(Root2))return true;elsereturn false;
}
•Find操作的优化

之前使用的Find操作是从指定节点出发,根据s[ ],向上找到所属根节点,这样向上的路径称为“查找路径”,而Find的优化操作就是要压缩这条路径,即压缩路径”。具体操作就是先找到根节点,再将查找路径上所有结点都挂到根结点下

例如下图,是执行节点L的查找路径:

压缩路径就是将图中蓝色的节点全部挂到A节点下。这样,从L节点向上找根节点的路径就被压缩了。

优化代码如下:

//Find"查"操作优化,先找到根节点再进行"压缩路径"
int Find(int S[],int x){int root = x;while(S[root]>=0)    root=S[root];  //循环找到根while(x!=root){ //压缩路径int t=S[x];    //t指向x的父节点S[x]=root;   //x直接挂到根节点下 x=t;}return root;    //返回根节点编号
}

每次 Find 操作,先找根,再“压缩路径”,可使树的高度不超过O(\alpha(n))\alpha(n)是一个增长很缓慢的函数,对于常见的n值,通常\alpha(n)≤4,因此优化后并查集的Find、Union操作时间开销都很低。

具体地,Find最坏时间复杂度O(\alpha (n))将n个独立元素通过多次Union合并为一个集合的最坏时间复杂度为O(n*\alpha (n))(n个元素需要合并n-1次)。

(2)并(Union):

•要想将两个集合“并”为同一个集合,可以将一棵树作为另外一棵树的子树。

//Union"并"操作,将两个集合合并为一个
void Union(int s[],int Root1,int Root2){//要求Root1与Root2是不同的集合if(Rootl==Root2)    return;//将根Root2连接到另一根Root1下面S[Root2]=Root1;
}
//时间复杂度:O(1)

S[Root2]=Root1达到的效果如下(假设要将以C为根节点的树合并为以A为根节点的子树):

刚开始Root1 = 0;Root2 = 2;将S[2]=0

也就是将C的父节点指向0号元素A

若想将n个独立元素通过多次Union合并为一个集合,最坏时间复杂度为O(n^2)。因为要合并n个独立的元素,需要n-1次Union,每一次Union之前需要从指定节点出发找到两个集合的根节点,而Find操作时间复杂度为O(n),所以重复n-1次的Union,最坏时间复杂度为O(n^2)。

•Union操作的优化

为了使“查”的效率更高,合并树时可以让小树合并到大树中,这样就不会增加树的高度了。

那么如何表示一棵树的大小呢?可以用根节点的绝对值表示树的结点总数。

例如下图2,以A为最左边树的根节点,A所对应的数组的值为-6,|-6|就是这棵树的节点总数。同理,以C为根节点的树有两个节点,以D为根节点的树有5个节点。

优化代码如下: 

//Union"并"操作,小树合并到大树
void Union(int S[],int Rootl,int Root2){if(Rootl == Root2)    return;if(S[Root2]>S[Root1]){     //Root2结点数更少    S[Root1]+= S[Root2];    //累加结点总数S[Root2]=Rootl;    //小树合并到大树} else {S[Root2]+= S[Root1];    //累加结点总数S[Root1]=Root2;    //小树合并到大树}
}
//改进的Union操作时间复杂度依旧是O(1)

用该方法优化“Union”操作后,构造的树高不超过\left \lfloor log_{2}n \right \rfloor+1,那么Find操作的最坏时间复杂度也能到O(log_{2}n),将n个独立元素通过多次Union合并为一个集合的最坏时间复杂度为O(n*log2^n)

总结:


http://www.ppmy.cn/embedded/18749.html

相关文章

mysql的多表查询和子查询

多表查询&#xff1a;查询数据时&#xff0c;需要使用多张表来查询 多表查询分类&#xff1a; 1.内连接查询 2.外连接查询 3.子查询 笛卡尔积&#xff1a; create table class (id int primary key auto_increment,name varchar(10) ); create table student (id int primar…

回归与聚类——性能评估(二)

1分析 回归当中的数据大小不一致&#xff0c;是否会导致结果影响较大。所以需要做标准化处理。 数据分割与标准化处理回归预测线性回归的算法效果评估 2回归性能评估 均方误差(Mean Squared Error)MSE)评价机制&#xff1a; 注&#xff1a;y^i为预测值&#xff0c;y-为真实…

Visual studio2022+QT的创建

Visual studio2022QT的创建 1.首先安装Visual studio 2.可以直接在visual studio中安装qt插件&#xff0c;如下所示&#xff1a; 扩展->管理扩展->搜索qt Vistal Studio Tools 3.接下来的就是重点&#xff0c;安装完了这个插件之后&#xff0c;也是需要安装qt的程序的…

网络运维类面试非技术问题

1、之前工作中网络架构 答&#xff1a;在上一家公司&#xff0c;我们的网络架构 &#xff08;或者我在做上一个项目时的网络架构&#xff09; 1&#xff09;在上家公司&#xff0c;采用了分层的网络架构模型&#xff0c;包括接入层、汇聚层、核心层和出口层 2&a…

前端HTML面试题:meta 元素都有什么

在HTML中&#xff0c;<meta> 元素是一个非常重要且常用的元素&#xff0c;它用于表示关于HTML文档的元数据&#xff08;metadata&#xff09;&#xff0c;这些元数据不会直接显示在页面上&#xff0c;但可以被浏览器以及其他网页服务利用。在前端开发的面试中&#xff0c…

IOptionService

目录 1、 IOptionService 1.1、 * 保存一组配置 2、 IUserService 2.1、 * 保存用户数据 2.2、 * 通过uid查找对象 2.3、 * 用戶登录

vue elementui 动态追加下拉框、输入框

vue elementui 动态追加下拉框、输入框 上代码&#xff1a; <template><div><el-dialogappend-to-body:close-on-click-modal"false":close-on-press-escape"false"width"65%"close"onClose":modal-append-to-body&q…

探索和构建 LLaMA 3 架构:深入探讨组件、编码和推理技术(五)RMS 均方根归一化

探索和构建 LLaMA 3 架构&#xff1a;深入探讨组件、编码和推理技术&#xff08;五&#xff09;RMS 均方根归一化 RMS&#xff08;均方根归一化&#xff09; 均方根归一化&#xff08;RMSNorm&#xff09;是一种相对新颖的归一化技术&#xff0c;由 Biao Zhu、Rico Sennrich …