并查集阐述及相关子函数详解

在计算机科学中,并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个用于此数据结构的操作:

Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
Union:将两个子集合并成同一个集合。
由于支持这两种操作,一个不相交集也常被称为联合-查找数据结构(union-find data structure)或合并-查找集合(merge-find set)。其他的重要方法,MakeSet,用于创建单元素集合。有了这些方法,许多经典的划分问题可以被解决。

为了更加精确的定义这些方法,需要定义如何表示集合。一种常用的策略是为每个集合选定一个固定的元素,称为代表,以表示整个集合。接着,Find(x) 返回 x 所属集合的代表,而 Union 使用两个集合的代表作为参数。
说白了,并差集就是看两者是否存在关系,是否在一个集合内,在图里面,常常判断两个点之间是否在一个集合内,是否连通。

并差集的操作,有查找父节点,合并父节点。(这里有路径压缩优化)
判断是否在同一个集合
接下来展示c++的代码

首先 要初始化,每个父亲节点是自己本身。
for(int i=1;i<=n;i++)
      fa[i]=i;
初始化完毕后,要查找父亲节点。
int find(int x)
{
  if(fa[x]==x)return x;
  //如果父亲节点是其本身,说明已经找到父亲节点
  else return fa[x]=find(fa[x]);
  //对于初学者,这里面是不是有点难理解呢?
  //这是个递归的过程,就是递归查找它的父节点是谁
}

并查集森林的两种改进策略:

1. 按秩合并(union by rank)。改进union操作的方法。这种方法的思想是在union操作中使较少节点的树的根指向具有较多节点的树的根,使得总是较小的树成为较大的树的子树。注意,这里并不显式地记录每个节点为根的子树的大小,而是采用一种易于分析的方法。对于每个节点,维护一个秩,它表示该节点高度的一个上界。在使用按秩合并策略的UNION操作中,我们可以让具有较小秩(高度)的根指向具有较大秩的根。我们初始化数组的所有项为-1。下图显示了一棵树及其对于按秩求并的实例。
  在这里插入图片描述
2. 路径压缩(path compression)。改进find操作的方法。它在查找过程中将查到节点到根的每个节点的父节点直接指向根。如下所示  在这里插入图片描述

第一种按秩合并实现代码
rank1[10005];
//要初始化rank1[i]=0;
for(int i=1;i<=n;i++)
rank1[i]=0;
void unit(int x,int y){
 x=find(x);
 y=find(y);
 //先调用find函数,找到父亲节点
 if(x==y)return;
 //父亲节点相同,说明在一颗树上或者说是在同一个集合内,无需操作
 if(rank1[x]<rank1[y])
 //x的这棵树高度小于y的高度
 fa[x]=y;//将它的父亲点直接改指向y
 else{
 fa[y]=x;
 if(rank1[x]==rank1[y])rank1[x]++;}
}
第二种路径压缩,实现起来比较容易
void unit(int x,int y){
 x=find(x);
 y=find(y);
 if(x!=y)
 fa[x]=y;
 //完成路径压缩,如果x和y不在同一颗树或者不在一个集合,将x指向y,他们的路径就压缩了
}

在这里插入图片描述

//判断x,y是否属于同一集合
bool same(int x,int y)
return find(x)==find(y);

https://blog.csdn.net/niushuai666/article/details/6662911
这个博客讲的比较通俗生动,如果有兴趣,可以移步这里。
小伙伴们,你是否懂了呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值