潇汀 2018-08-29
用树实现的并查集
接口
public interface UF{
int getSize();
boolean isConnected(int p,int q);
void unionElements(int p,int q);
}
public class UnionFindV6 implements UF{
//孩子指向父亲
private int[] parent;//parent[i] 表示的第i个元素指向的父节点
private int[] rank;//sz[i]表示以i为根的集合中元素的个数
/**
* 构造函数
*/
public UnionFindV6 (int size) {
parent = new int[size];
rank = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;//初始的时候,每一个节点都指向它自己
rank[i] = 1;
}
}
@Override
public int getSize() {
return parent.length;
}
//查找过程,查找元素p所对应的的集合编号
//O(h)复杂度,h为树的高度
//这里用递归,需要返回值的 int
//最后树只有两层
private int find(int p) {
if (p < 0 && p >= parent.length) {
throw new IllegalArgumentException("p is out of bound");
}
//****路径压缩
if (p != parent[p]) {//判断是否是根节点
//直接挂接到根节点
parent[p] = find(parent[p]);
}
return parent[p];
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
@Override
public void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) {
return;
}
// 根据两个元素所在数的rank不同判断合并方向 【这里的rank指深度】
// 将rank低的集合合并到rank高的集合上
if (rank[pRoot] < rank[qRoot]) {
parent[pRoot] = qRoot;
} else if (rank[pRoot] > rank[qRoot]) {
parent[qRoot] = pRoot;
} else {//rank[pRoot] == rank[qRoot]
parent[qRoot] = pRoot;
rank[pRoot] += 1;
}
}
}