不相交集类是解决等价问题的一种有效数据结构,实现简单,代码很少,速度快。
基本思想
等价关系
对于任意一对元素a,b∈S,定义关系~ ,使得a~b要么为true要么为false
1.(自反性)对于所有的a∈S,a~a
2.(对称性)a~b当且仅当b ~ a
3.(传递性)若a~b且b ~ c则a ~ c
等价类 :对于元素a∈S,等价类是S的一个子集,包含所有与a有等价关系的元素。S的每个成员恰好在一个等价类中
不相交集:设有N个集合的类,每个集合含有一个不同元素,所有的元素两两不等价,那么这些集合不相交
union/find算法:对于这些不相交集,有两种操作方式:find,返回等价类的名字;union,将两个等价类合并
实现这个算法最简单的操作是以森林的方式给出,这个森林隐式地位于一个数组中
数组的角标代表元素,角标上的值代表元素的父节点,默认只有一个元素的等价类根为-1
算法实现
public class DisjSets
{
private int[] s;
//初始化
public DisjSets(int numElement)
{
s = new int[numElement];
for(int i = 0; i < numElement; i++)
s[i] = -1;
}
//按秩求并:根的数据为秩-1
public void union(int root1, int root2)
{
if(s[root2] < s[root1]) //root2更深
s[root1] = root2; //roo2成为新的根
else
{
if(s[root2] == s[root1])
s[root1]--; //相同则树的高度增1
s[root2] = root1; //root1成为新的根
}
}
//路径压缩的find
public int find(int x)
{
if(s[x] < 0) //x为根
return x;
else
return s[x] = find(s[x]);
//x所在路径的所有节点的父节点都是根
//s[x] = s[s[x]] = ... = root
}
}
可以看出,每个方法近乎是以常数的时间运行
不相交集类的一个例子是迷宫的生成,这里不再赘述