转载的并查集博客
原文在此:http://www.cnblogs.com/noKing/p/8018609.html
并查集
最主要是两个函数
(1)find(x):判断x的父母
(2)union(x,y):合并x和y
路径压缩就是处理并查集中的深的结点。实现方法很简单,就是在find函数里加上一句 parent[element] = parent[parent[element]];就好了,就是让当前结点指向自己父亲的父亲,减少深度,同时还没有改变根结点的weight(非根节点的weight改变了无所谓)。
注:只能在基于重量的并查集上改find函数,而不能在基于高度的并查集上采用这种路径压缩。因为路径压缩后根的重量不变,但高度会变,然而高度改变后又不方便重新计算。
public class UnionFind {
private int[] parent;
private int[] weight;
private int size;
public UnionFind(int size) {
this.parent = new int[size];
this.weight = new int[size];
this.size = size;
for (int i = 0; i < size; i++) {
this.parent[i] = i;
this.weight[i] = 1;
}
}
public int find(int element) {
while (element != parent[element]) {
parent[element] = parent[parent[element]];
element = parent[element];
}
return element;
}
public boolean isConnected(int firstElement, int secondElement) {
return find(firstElement) == find(secondElement);
}
public void unionElements(int firstElement, int secondElement) {
int firstRoot = find(firstElement);
int secondRoot = find(secondElement);
//如果已经属于同一个集合了,就不用再合并了。
if (firstRoot == secondRoot) {
return;
}
if (weight[firstRoot] > weight[secondRoot]) {
parent[secondRoot] = firstRoot;
weight[firstRoot] += weight[secondRoot];
} else {//weight[firstRoot] <= weight[secondRoot]
parent[firstRoot] = secondRoot;
weight[secondRoot] += weight[firstRoot];
}
}
}