并查集
定义
“合并集合Union”和“查找集合中的元素的标识符Find”的一种操作
目的
解决动态联通问题,也即判断任意给定两个元素是否在同一个等价类(自反,对称,传递)中find,以及如果不在同一个等价类中,如何快速union
基本的方法(Java)
UnionFind(int N) : 初始化并查集,并查集中包含N个互不相连的对象
void union(int p, int q) : 连接p,q
int find(int p) : p所在的连通分量的标识符
boolean connect(int p, int q) : 返回p、q是否在同一个连通分支内
int count() : 连通分量的数量
可以用一个长度为N的整数数组来表示一个并查集的数据结构,通过索引来直接查找parent,下标为i的元素的值是指i对象对应的连通分量的标识
索引为0的位置不放任何元素
整体框架(Java)
public class UnionFind{
int[] parent;
int count;
public int count(){
return count;
}
public boolean connected(int p, int q){
return find(p) == find(q);
}
public int find(int p){
}
public int union(int p, int q){
}
}
一种不太好的Union实现方式
上面的这种方法,在极端情况下,Find的时间复杂度会比较高,趋向于O(N),链表是线性的
改进Union
Weight rule:如果树I的nodes数比树J的少,那么让J成为I的parent
Height rule:如果树I的高度比树J低,那么让J成为I的parent
Height规则
Weight规则
Weight规则里的root数组is true iff the node is presently a root node
整理一棵给定的树使得find次数最少
最后再find,那么find的次数最少
public int find(int x){
if(parent[x]<0)
return x;
else
return parent[x]=find(parent[x]);
}