1、一个元素a属于S的等价类是S的一个子集,它包含所有与a有(等价)关系的元素。
2、不相交集:N个集合的类,每个集合含有一个元素,所有集合间的关系均为false(除自反关系外),每个集合都有一个不同的元素,从而得到Si∩Sj=Φ,为不相交集。
3、不相交集的两种操作:
1)find(),返回包含给定元素的集合的名字。
2)添加关系:添加关系a˜b
首先判断a和b是否在同一个等价类中,用find来实现,若是(在同一个等价类中),不用操作。否则,操作union,将a和b的两个等价类合并成一个新的等价类。利用的是不相交集合的union/find算法。
4、不相交集合的union/find算法
1)属于动态算法;
2)该算法是联机(on-line)操作的:当find时,必须给出答案才能继续进行下一步。
3)另一种可能是脱机(off-line)算法:该算法需要观察全部的union和find序列。它对每一个find给出的答案必须和所有被执行到该find的union一致,但是该算法在看到这些问题以后才能够给出它的所有答案。
另外,find(a) == find(b)若为true当且仅当a和b在同一个集合中。
5、不相交集合类的基本数据结构的实现:
package 不相交集;
public class DisjointSets {
private int[] s;
//不相交集合的初始化
public DisjointSets(int numElement){
s = new int[numElement];
for(int i = 0; i < s.length; i++){
s[i] = -1;
}
}
//不相交集合的union()方法一,该方法存在缺陷,只能将一个集合固定的接到另一个集合中,形成新的集合
public void union(int root1, int root2){
s[root2] = root1;
}
//不相交集合的union()方法二,按照高度来合并两个集合
public void union2(int root1, int root2){
if(s[root2] < s[root1]){//root2更深一些,则以root2为根(代表)建立新的集合
s[root1] = root2;
}else{
if(s[root2] == s[root1]){
s[root1]--;//如果两个集合的高度相同,则更新高度
}
s[root2] = root1;//s[roo1] < s[root2],root1更深一些
}
}
//不相交集合的find()方法一
public int find(int x){
if(s[x] < 0){//Si = -1表示根结点,若s[x]<0,则表示x为集合的根
return x;
}else{
return find(s[x]);
}
}
//用路径压缩对不相交集合进行find()的方法二
public int find1(int x){
if(s[x] < 0){
return x;
}else{
return s[x] = find(s[x]);
}
}
}