并查集及其Java实现
并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。一般在集合的关系查找中使用较多(两个元素是否属于同一集合)百度百科
- Java代码以及测试类
import java.util.Arrays;
import java.util.Scanner;
public class UnionSearch {
private int[] id; //记录每个子集的“上司”(父节点)
private int count; //记录子集个数
public UnionSearch(int N) { //初始化并查集,开始每个节点父节点默认为自身
id = new int[N];
count = N;
for(int i = 0; i < N; i++)
id[i] = i;
}
public int getCount() { //获取并集后的个数
return count;
}
public int[] getId() { //获得每个个体的“上司”数组(并不一定是”顶头上司“)
return id;
}
public boolean connected(int p, int q) { //判断两个个体是否在同一子集之中
return find(p) == find(q);
}
public int find(int p) { //寻找个体p的”顶头上司“(根节点),只有根节点的父节点是自身
while(p != id[p])
p = id[p];
return p;
}
public void union(int p, int q){ //将个体p合并进个体q所在子集之中
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot) //两个个体原本位于同一子集之中,无需操作
return;
id[pRoot] = qRoot; //两个个体位于不同子集之中,需将p个体父节点修改为q节点的根节点即可
count--;
}
public int[] rootArr(int N){ //返回每个个体的根节点(所在子集)数组
int[] rootArr=new int[N];
for (int i = 0; i < N; i++) {
rootArr[i]=find(i);
}
return rootArr;
}
}
class testUnion{ //测试类
public static void main(String[] args) {
Scanner r = new Scanner(System.in);
int N = r.nextInt(); //初始化N个个体,0~N-1
int M = r.nextInt(); //M组两两合并关系
UnionSearch quickunion = new UnionSearch(N); //初始化并查集
for (int i = 0; i < M; i++) { //输入M组合并关系数组
int temp1=r.nextInt();
int temp2=r.nextInt();
quickunion.union(temp1,temp2);
}
System.out.println(quickunion.connected(1,2)); //判断两个节点是否在同一子集之中
System.out.println(Arrays.toString(quickunion.getId())); //得到合并后的每个节点的”上司“节点
System.out.println(quickunion.getCount()); //得到合并后的子集个数
System.out.println(Arrays.toString(quickunion.rootArr(N))); //得到每个节点所在子集数组
}
}
- 输入输出测试样例
博客中相关问题欢迎询问探讨,相互学习。QQ:1476154032,以上。