四、内功算法之连通性问题路径压缩优化查询

版权声明:话不在多,在于精 https://blog.csdn.net/qq_29857681/article/details/88788016

问题:虽然不会生成很高得树,但是在查询时还是一步一步得查找根节点,这块还能优化

思路:在查询根节点时,将当前得根节点设置为爷爷节点,从而下次在查询时,原查询路径缩短为一半,节点越多,效果越明显。

代码实现

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];
        }

    }
}

猜你喜欢

转载自blog.csdn.net/qq_29857681/article/details/88788016