问题:虽然不会生成很高得树,但是在查询时还是一步一步得查找根节点,这块还能优化
思路:在查询根节点时,将当前得根节点设置为爷爷节点,从而下次在查询时,原查询路径缩短为一半,节点越多,效果越明显。
代码实现
package com.jd.testjava.algorithm;
/**
* 连通性问题
* 使用树结构实现
* 快速合并算法优化(将小树合并到大树下面,避免大树合并到小树,高度成倍增长)
* 带权(高度)快速合并算法
*
* @author lichenyang8
* @date 2019/3/25
*/
public class QuickUnionAlgorithmPlus implements IAlgorithm{
private int[] ids;
private final int length;
//统计树高
private int[] sz;
/**
* 初始化数组
* @param length
*/
public QuickUnionAlgorithmPlus(int length){
this.length = length;
ids = new int[length];
sz = new int[length];
for (int i = 0; i < length; i++) {
ids[i] = i;
sz[i] = 1;
}
}
/**
* 查询根节点
* 自己的根节点等于自身,则为根节点
*/
private int getRoot(int p){
while (ids[p] != p){
//将p的根设置为p的爷爷 从而实现路径压缩,访问节点减少为原来的一半
ids[p] = ids[ids[p]];
//用爷爷去寻找真正的根
p = ids[p];
}
return p;
}
/**
* 查询是否联通
* 根节点相同则为联通
*/
@Override
public Boolean isConnect(int p, int q){
return getRoot(p) == getRoot(q);
}
/**
* 连通两个节点
* @param p
* @param q
*/
@Override
public void connect(int p, int q){
//获得p的根
int pid = ids[p];
int qid = ids[q];
if (pid == qid) return;
//sz[pid] 表示p所在树的高度
if (sz[pid] < sz[qid]){
/**
* 小树合并到大树
*/
//将pid的根换成qid
ids[pid] = qid;
//维护以qid为根的树高
sz[qid] += sz[pid];
}else{
ids[qid] = pid;
sz[pid] += sz[qid];
}
}
}