将每一个元素,看做是一个节点
下面是模拟 我一个个吧老师模拟的图片给发出来
union 4,3 4指向了3
子节点指向根节点
3指向8
6指向5
9指向4
7指向2
6指向2
查找元素
一样的先判断边界,然后只要查找的元素和不相等就循环 找到相同 p=parent[p]
/**
* 查找过程,查找元素p所对应的集合编号
* O(h)复杂度,h为树的高度
* @param p
* @return
*/
private int find(int p){
if(p < 0 && p>=parent.length)
throw new IllegalArgumentException("下标不合法");
while(p !=parent[p])
p=parent[p];
return p;
}
是否属于一个集合,没有修改
主要是合并
先查找p,q的元素,如果相等,那么肯定是1相同集合,就没有必要合并,直接返回空
这里判断小于大于这些,是为了节约空间
//查找元素p和元素q是否所属一个集合
@Override
public boolean isConnected(int p,int q){
return find(p) == find(q);
}
/**
* 合并元素p和元素q所属的集合
* O(h)复杂度,h为树的高度
*/
@Override
public void unionElements(int p,int q){
int pRoot=find(p);
int qRoot=find(q);
if(pRoot == qRoot)
return ;
//根据两个元素所在树的元素个数不同判断合并方向
//将元素个数少的集合合并到元素个数多的集合上
if(rank[pRoot] < rank[qRoot])//如果pRoot元素高度小于 就指向高的元素 pRoot=qRoot
parent[pRoot] = qRoot;//pRoot 指向qRoot
else if(rank[qRoot] < rank[pRoot])//反之亦然 q小于p qRoot就指向pRoot parent[qRoot]=parent[pRoot]
parent[qRoot]=pRoot;//qRoot 指向pRoot
else{//rank[qRoot] == rank[pRoot]
parent[qRoot]=pRoot;
rank[pRoot]+=1;//高度加1
}
}