并查集Union-Find

本文介绍了并查集(Disjoint Sets)的概念,包括Make-Set、Union和Find-Set操作。讨论了不同实现方式,如Disjoint-Sets Array、Disjoint-Sets Linked-List和Disjoint-Sets Forests,以及优化策略——权重合并(Union by rank)和路径压缩。权重合并通过比较子树长度避免树形结构失衡,路径压缩则通过直接指向根节点减少查找时间。两种优化结合后的平均时间复杂度接近线性。

坑越挖越大实在不厚道,开始填

http://blog.youkuaiyun.com/dm_vincent/article/details/7655764
这个写得很易懂了,不打算摘转,请大家直接看原文
并参考了《Introduction to Algorithms》,这里用自己的方式归纳下

1)互斥集(Disjoint Sets)
不相交集合们形成的整体
「建模」元素本身+集合编号(唯一代表,representative)
Operations
Make-Set(x), create a new set whose only member is x.
Union(x, y), in practice, we often absorb the elements of one of the sets into the other set.(合并集合,一边的代表指针指向另一边)
Find-Set(x), returns a pointer to the representative of the (unique) set containing x.(找找元素在哪个集合,返回集合的代表指针)

一般问题域,如「MST」中的判断新加入edge(a, b),产生的连通性影响
INPUT: Disjoint Sets, edge(a, b)
OUTPUT: a、b来自不同集合则Union then return new Disjoint Sets, or not

a)Disjoint-Sets Array
arr[5] = 3; // 第5个元素在第3个集合
Find很高效,仅仅一次数组读取操作

但,每Union一条edge(a, b),需要遍历数组,更改其所属集合编号,时间线性
一般问题域中可能需要多次调用,即N条edge时间复杂度O(N^2)

b)Disjoint-Sets Linked-List
这里写图片描述
a pointer to the next object in the list
a pointer back to the set object
*weighted-union heuristic

c)Disjoint-Sets Forests
这里写图片描述
以树型结构构建的互斥集森林

arr[5] = 3; arr[3] = 1; arr[1] = 0; arr[0] = 0;
第5个元素和第3个元素同属一个集合
第3个元素和第1个元素同属一个集合
第1个元素和第0个元素同属一个集合
if(arr[index] == index) return index; // 抵达根节点,返回所属集合编号
「Find Path」5-3-1-0,O(N)

Union,修改一遍集合的根节点指针,使其指向另一边集合的根节点

worst case and heuristic to improve,look at next chapter

2)Union by rank with path compression
a)Union by rank(weighted-union)
也就是权重合并Weighted-Union,similar
Union的操作,arr[left_root] = right_root,会使得左子树高度增加一层,如果左子树本身就比右子树高深,则合并后的树会更畸形
采用rank[]等记录各子树的length,合并时比较,将小数挂在大树上,并更新rank
保证了合并后树的深度,单独使用O(mlgn) for m disjoint-sets operations and n elements

b)路径压缩Path Compression
这里写图片描述
使得节点尽量直接指向根,毫无疑问会节省Find时间
I) 在「Find Path」找到根节点后,进行路径压缩
在循环找根的过程中,保存中间节点
在循环结束找到根后,将中间节点指向根节点

II) 在「Find Path」过程中,同时进行路径压缩
在循环找根的过程中,同时将该中间节点指向其爷爷节点,毫无疑问进行了一定程度的压缩
while (target != arr[index]) {
arr[index] = arr[arr[index]]; // 指向其爷爷节点
target = arr[index]; // 一次跳两步,因arr[root] == root,所以并不会溢出
}

保证了子树路径深度,单独使用时间复杂度较长不列…

同时使用权重合并和路径压缩,O(mα(n)), where α(n) is very slowly growing function. In any conceivable application of disjoint-set data structure, α(n) <= 4. 因此,我们可以认为实际中,运行时间趋于线性。

更多证明详见书21.4.Analysis of union by rank with path compression
你可以认为「并查集」算法就是「互斥集」建模后一般应用形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值