并查集

来源:互联网 发布:苏州软件测试 编辑:程序博客网 时间:2024/05/16 00:24

定义

并查集也是不相交集,存放数据的集合关系,如{1,2} {3,4,6} {5}。输入数据最初是N个集合,每个集合含有一个元素。初始的描述是所有的关系均为false。每个集合含有一个元素,这使得这些集合不相交。
ADT:
 建立新集合
 查找某个元素属于哪个集合
 合并两个集合
时间复杂度O(1)

集合S上的关系

如果对于每一对元素(a,b),a,bS,aRb或者为true,或者为false,则称在集合S上定义关系R。aRb=true,说明a与b有关系。S是一次解决问题所有元素的集合。例如要解决一个国家所有城市的空运问题,那S就是全部城市;如果要解决北上广空运问题,那S={北京,上海,广州}。

等价关系

等价关系是满足三个性质的关系:
1 自反性。对于所有的aS,aRa。
2 对称性。aRb当且仅当bRa(a与b有关系当且仅当b与a有关系)。
3 传递性。若aRb 且 bRc,则aRc。
关系<=就是不是等价关系。因为a<=b,不能得出b<=a。
等价关系的符号:~。

动态等价关系

对于一个等价关系~,对于任意的a和b确定是否a~b。

等价类

一个元素a\inS的等价类是S的一个集合,它包含所有与a有等价关系的元素。
等价类是对S的一个划分:S的每一个成员恰好出现在一个等价类中。为确定a~b,只需要验证a和b是否都在同一个等价类中。

ADT

1 建立新集合
2 查找。查找某个元素属于哪个集合。
3 合并。合并两个集合为1个集合。

数据结构

采用树表示每一个等价类(集合)。
1 初始的时候每个集合包含一个元素。如果S={1,2,3,4,5,6,7,8}。数组s[i]表示每个元素i的父亲。如果i是根节点,那么s[i]=-1。
初始树
这里写图片描述

初始数组表示




-1-1-1-1-1-1-1-1 12345678

2union操作
union(5,6)
这里写图片描述
union(7,8)
这里写图片描述
union集合{5,6}和{7,8}。图中显示的是{7,8}成为了{5,6}的子树。合并操作一定是在其中一个集合的根节点进行。如果想要在节点6合并,那元素6就有两个根,数组没法表示。通常的操作是将一棵树的根链接到另一棵树的根。好处是方便表示,被合并的树又不会特别深。
这里写图片描述




-1-1-1-1-1557 12345678

3 find,查找元素i属于哪个集合。首先要可以以常数时间找到i节点。接着从i节点的元素开始递归的查找到是s[i]=-1的i节点就是根节点。例如查找元素8:s[8]=7,s[7]=5,s[5]=-1,停止查找,根节点是5。查找元素7,:s[7]=5,s[5]=-1,停止查找,根节点是5。说明8和7在同一个集合中:8~7=true。

union操作优化

上一节的合并是在相同大小的集合之间进行的。如果按照任意顺序进行下去很可能构造一棵N-1深度的树。深度越深查找越慢。优化方法有两种。
1 按照集合大小合并。元素个数小的树成为元素个数大的树的子树。那么s[i]=-集合大小。
2 按照高度合并。浅的树成为深的树的子树。s[i]=-集合高度-1。
按照任意排序可能是这样。
这里写图片描述
按照高度合并是这样。
这里写图片描述




-1-1-15-3557 12345678
上面的描述对union/find操作对大多数情形都是可以接受的。连续M个指令,平均是闲心的。不过O(MlogN)的最坏情况还是可能发生的。如果find操作与union操作多,则情形不太乐观。所以进行路径优化。

路径压缩-优化find操作

路径优化是在find过程中进行的。思路是:执行一次find操作,把路径上所有的节点直接指向根节点,而不需要父节点。
例如对上面的图进行一次find(8)以后,8直接指向父节点5,而不再指向7。这里有信息丢失,但是对于只判断两个元素是否在同一个集合中的功能来说,丢失的信息是无关紧要的。




-1-1-15-3555 12345678

应用

1 可用于图的最小生成树。
2 生成迷宫。

参考资料:
1 《数据结构域算法分析Java语言描述》第二版
2 七月算法面试课程
3 http://blog.csdn.net/spch2008/article/details/9338943

0 0