带权重的union_find可以有效降低树的高度,从而提高效率
package com.company;
/**
* meng3.wei
* 2020.02.16
* 带权重的union-find
* 带权重,可以保证小的树会被挂在大的树上,以保证树不会太高(随机挂载由于树的高度问题,性能会变低)
*/
public class UnionFind {
private int count;//连通分量的个数
private int[] pid;//保存父亲连接节点的id
private int[] sonSize;//保存各个节点作为根节点的分量大小
public UnionFind(int N){
count=N;
pid=new int[N];
sonSize=new int[N];
for (int i = 0; i < N; i++) {
pid[i]=i;
sonSize[i]=1;
}
}
/**
* 将p和q链接起来
* @param p
* @param q
*/
public void union(int p,int q){
int m=find(p);
int n=find(q);
if(m==n){//两个点的顶级父节点相同,则这两个点已经是联通的
return;
}
pid[n]=m;//n的父亲节点改成m
//if(sonSize[m]>=sonSize[n]){//m是大树,n是小树,小树n需要挂到大树m上
// pid[n]=m;//n的父亲节点改成m
// sonSize[m]=sonSize[m]+sonSize[n];
// }else {
// pid[m]=n;
// sonSize[n]=sonSize[n]+sonSize[m];
//}
count--;
}
/**
* 判断p和q是否连接
* @param p
* @param q
* @return
*/
public boolean connected(int p,int q){
int m=find(p);
int n=find(q);
return m==n;
}
/**
* 找个这个节点的顶级父节点
* @param p
* @return
*/
public int find(int p){
int temp=p;//先用temp保存下当前的节点p,因为p一会要变成p的顶级根节点
while(pid[p]!=p){
p=pid[p];
}
while(pid[temp]!=p){//路径压缩一下,都挂在顶级根节点上
int a=temp;
temp=pid[temp];
pid[a]=p;//一路上的节点,都挂在顶级根节点p上
}
return p;
}
public int count(){
return count;
}
}
参照了以下代码,但是还尚有不理解的地方