首先,什么是等价关系:
等价关系是集合元素间的一种代数关系,用字母E来表示,对于一个集合中的两个元素,如果他们之间存在一种等价关系,那么必须满足以下性质:
1. 自反性,对于任意一个元素x, 它与自己存在等价关系,即(x,x) 满足E
2. 对称性,如果(x,y) 满足 E, 那么 (y, x) 也属于E
3. 传递性,如果(x,y) 满足 E,(y,z)满足E,那么(x,z)也满足E.
接下来,看下面一个等价类的算法:
假设有集合S: {1, 2, … n-1}. 同时有两个数组A,B,他们的元素都来自集合S,且长度都是m, A,B 两数组用来确定集合S 中元素的等价关系,假定A[k] 与 B[k]是等价的,那么S便会被划分成几个不相交的等价类子集,例如:
n = 7,m=4,
假定:
A = {1, 5, 3, 6}
B = {2, 1, 0, 5}
于是S便会被划分成3个不相交的等价类子集:
S1 = {0, 3}
S2 = {1, 2, 5, 6}
S3 = {4}
给你一个数组S, 以及数组A,B, 要求你计算出S被划分的等价类子集。
一种方法是,用队列,把等价的各个元素链接起来,那么互相链接的类就是等价类。
另一种方法是利用等价类的传递性,如果A与B等价,B与C等价那么A与C也等价。
代码如下:
public class Number {
public int val;
public ArrayList<Integer> set = null;
public boolean visited = false;
public Number(int val) {
this.val = val;
set = new ArrayList<Integer>();
set.add(val);
}
}
public class EquivalClass {
private Number[] numArray = null;
public EquivalClass(int n, int[] A, int[] B) {
numArray = new Number[n];
for (int i = 0; i < n; i++) {
numArray[i] = new Number(i);
}
for (int i = 0; i < A.length; i++) {
int a = A[i];
int b = B[i];
makeSet(numArray[a], numArray[b]);
}
}
private void makeSet(Number a, Number b) {
a.set.addAll(b.set);
b.set = a.set;
}
public void printAllEquivalSet() {
for (int i = numArray.length - 1; i >= 0; i--) {
printEquivalSet(numArray[i]);
}
}
private void printEquivalSet(Number number) {
if (number.visited == true) {
return;
}
number.visited = true;
System.out.print("{ ");
Iterator<Integer> it = number.set.iterator();
while (it.hasNext()) {
int v = it.next();
System.out.print(v + " ");
numArray[v].visited = true;
}
System.out.println(" }");
}
}