不相交集(并查集)

不相交集是解决等价问题的一种有效的数据结构。

一、等价关系

等价关系定义如下:
1) 自反性:对于所有的a属于集合S, a与a有关系;
2) 对称性:如果a与b 有关系, 则b与a 有关系;
3) 传递性:如果a有b 有关系, b与c有关系, 则a 与 c 有关系;
在不想交集类中, 所有具有等价关系的类都在一个集合中,称为等价类; 不同的集合之间不存在等价关系;
为确定a 和 b是否具有关系, 我们只需要确定a 和 b 是否属于同一个等价类中;

一开始, 输入数据是N个数据, 每一个数据就是一个等价类(每个等价类中只有iyge元素);因此,初始时候,每个元素都是不相交的;
对不相交集允许两种操作:
1) find 操作
find 函数返回包含给定元素 的等价类的名字;
2) union 操作
如果要在a 和 b 之间建立等价关系, 首先需要确定a 和 b 是否已经具有等价关系了, 这可以通过对a 和 b执行find操作并检验他们是否在同一个等价类中完成。如果a 和 b 之间没有等价关系, 就将a 和 b 的两个等价类合并成一个新的等价类。

注意, 我们不进行任何比较元素相关的值得操作,只需要知道他们的位置。因此, 可以假设所有的元素均已从0到N-1 顺序编号, 并且编号方法容易由某个散列方案确定;
find操作返回的等价类的名字是很随意的, 不同的情况下a元素的等价类的名字可能会不同, 确定a 和 b是否有等价关系, 只要的是find(a) == find(b)

不相交集的find的操作在最坏的情况下运行时间为常数(当集合中每一个元素都是一个等价类的时候);
union 操作的最坏运行时间是常数(两个最大等价类合并到时候);
上述两个操作不能同时以常数最坏运行时间运行;

在执行union的时候, 通常将较小的等价类的名字改成较大的等价类的名字, 对于N-1 次合并到总的时间开销为O(NlogN)。 其原因在于, 每个元素可能将它的等价类最多改变logN 次;因此, 每次等价类改变时他的新的等价类至少是其原来等价类的两倍大小。使用这种方法, 任意顺序的M次find 和 N-1次union 最多花费 O(M + NlogN)的时间;

二、数据结构

使用树结构表示一个等价类, 树的集合是森林, 森林表示等价类的集合;
等价类的名字就是树的根;
使用一个数组, 数组的每个成员s[i] 表示元素i的父亲, 如果元素i是根, 那么s[i] = -1;

union 操作:
将一棵树的根雕父链 链接到另一棵树的根结点, 从而合并这两棵树。
find 操作:
对元素x的一次find(x) 操作通过返回这棵树的根完成;执行find的操作花费的时间与x结点深度成正比;x结点的深度可能是N-1,因此find操作的最坏情形的代价是O(N);
M次连续操作的最坏情形是O(MN);

相关代码如下:

class DisjSets {
   
public:
	explicit DisjSets(int numElements);
	int fin
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值