ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于并查集

2022-05-03 20:03:47  阅读:154  来源: 互联网

标签:parent int 查集 rank find 关于 集合 节点


并查集,顾名思义,就是合并、查找集合:

对于一个集合S={a1, a2, ..., an-1, an},我们还可以对集合S进一步划分: S1,S2,...,Sm-1,Sm。我们希望能够快速确定S中的两两元素是否属于S的同一子集。

主要是两个操作:

1、Find查找元素所属集合

2、Union合并两个集合成一个新的集合

 

基本解析:

可以用树来表示这种数据结构——集合。最初的时候每一个元素都是一个集合 。                  

那如果我们现在想把{0}和{1}合并成一个集合{0,1}该怎么办呢?那就要自定义并使用Union函数(具体代码实现下文会提及)

然而如果我想判断两个元素是否在同一个集合中,就可以用Find函数来实现

 

代码思想:

首先定义一个parent数组来表示元素的父结点。

对于Find操作,因为每个集合都会有一个打头的根结点,所以对于任意两个元素,我们只要看他们所属的集合(树)的leader(根结点)是否是一样的就可以判断他们是否在同一个集合内

int find(int x)
{
    return parent[x] == x ? x : find(parent[x]);
}

这就是find操作,值得注意的是,如果x=parent[x],那就说明已经找到了根结点。那就可以跳出并返回自己了。(也就是元素的根节点),最后我们只要比较find[x]是否等于find[y]就可以判断x和y是否在同一集合内(是否有同样的根节点)

 

那怎样实现union操作呢?

传入两个元素,分别找到根节点,使根节点p1的父节点为p2,即将p1为根节点的这棵树合并到p2为根节点的树上。

void to_union(int x1, int x2) 
{
    int p1 = find(x1);
    int p2 = find(x2);
    parent[p1] = p2;
}

 

哈哈,都听懂了吧,但别高兴的太早!!!

用脚指头想想,每次find的操作复杂度都是树的高度o(h),如果这棵树的每一个结点(根节点和叶节点除外)都只有一个出度和一个入读,那很好,你就得到了o(n)的复杂度。。。

这可不是AC人士的标配啊,那可咋没办?

 

 方法一:那就要路径压缩啦!!!

“路径压缩”。在执行Find的过程中,将路径上的所有节点都直接连接到根节点上。

 方法二:"按秩合并"

实际上就是在合并两棵树时,将高度较小的树合并到高度较大的树上。这里我们使用“秩”(rank)代替高度,秩表示高度的上界,通常情况我们令只有一个节点的树的秩为0,严格来说,rank + 1才是高度的上界;两棵秩分别为r1、r2的树合并,如果秩不相等,我们将秩小的树合并到秩大的树上,这样就能保证新树秩不大于原来的任意一棵树。如果r1与r2相等,两棵树任意合并,并令新树的秩为r1 + 1
代码:
 1 int find(int x)
 2 {
 3     if(x==parent[x])
 4     {
 5         return x;
 6     }
 7     else 
 8     {
 9         parent[x]=find(parent[x]);
10         return find(parent[x]);
11     }
12 }
13 
14 void to_union(int x1, int x2)
15 {
16     int f1=find(x1);
17     int f2=find(x2);
18     if(rank[f1]>rank[f2])
19     {
20         parent[f2]=f1;
21     }
22     else
23     {
24         parent[f1]=f2;
25         if(rank[f1]==rank[f2])
26         {
27             rank[f2]++;
28         }
29     }
30 }

就先到这吧

拜拜!



标签:parent,int,查集,rank,find,关于,集合,节点
来源: https://www.cnblogs.com/zch061023/p/16091534.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有