并查集
并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。
package leetcode;
/**
* 并查集
* 并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。
* 以下实现是,考虑rank树高的
*/
public class UnionFind{
private int[] parent;//父亲结点
private int[] weight;//重量,集合中node的数量
private int size;
public UnionFind(int size){
this.parent = new int[size+1];
this.weight = new int[size+1];
this.size = size;
for (int i = 0; i < size; i++){
this.parent[i] = i;
this.weight[i] = 1;
}
}
/**
* 查找find
* 路径压缩:让当前结点指向自己父亲的父亲,没有改变根结点的weight(非根节点的weight改变了无所谓)。
*
* 找寻节点的根节点
* @param node 节点
* @return 返回节点的根节点
*/
public int find(int node){
while(node != parent[node]){
parent[node] = parent[parent[node]];//路径压缩
node = parent[node];
}
return node;
}
/**
* 还是有并查集深度太深的问题。并查集越深,就越接近线性,find函数就越接近O(n)
* 所以有了这种基于高度的union。合并时,选择将weight少的合并到weight多的集合中
*
* 合并两个节点
* @param node1 第一个结点
* @param node2 第二个结点
*/
public void union(int node1, int node2){
int node1Root = find(node1);
int node2Root = find(node2);
if(node1Root == node2Root){
return;
}
if (weight[node1Root] > weight[node2Root]){
parent[node2Root] = node1Root;
weight[node1Root] += weight[node2Root];
}else{//weight[node1Root] <= weight[node2Root]
parent[node1Root] = node2Root;
weight[node2Root] += weight[node1Root];
}
}
/**
* 判断两个节点是否属于同一个集合
* @param node1 第一个结点
* @param node2 第二个结点
* @return 如果是则返回true
*/
public boolean isConnected(int node1, int node2){
return find(node1) == find(node2);
}
/**
* 打印,输出parent,weight数组,展示
*/
public void printArr(){
for(int p : parent){
System.out.print(p+"\t");
}
System.out.println();
}
/*
public static void main(String[] args){
int n = 10;
UnionFind union = new UnionFind(n);
System.out.println("初始:");
union.printArr();
System.out.println("连接了5 6");
union.union(5, 6);
union.printArr();
System.out.println("连接了1 2");
union.union(1, 2);
union.printArr();
System.out.println("连接了2 3");
union.union(2, 3);
union.printArr();
System.out.println("连接了1 4");
union.union(1, 4);
union.printArr();
System.out.println("连接了1 5");
union.union(1, 5);
union.printArr();
System.out.println("1 6 是否连接:" + union.isConnected(1, 6));
System.out.println("1 8 是否连接:" + union.isConnected(1, 8));
System.out.println("2 5 是否连接:" + union.isConnected(2, 5));
System.out.println("2 5 是否连接:" + union.isConnected(6, 5));
System.out.println("连接了8 5");
union.union(8, 5);
union.printArr();
System.out.println("8 3 是否连接:" + union.isConnected(8, 3));
}*/
}