并查集 06 路径压缩

基于路径压缩的并查集

  • 把rank小的树合并到rank大的树中,这已经是合并时的优化行为了,但是,随着合并次数的增多,树会越来越多,其实树的形状是有进一步优化的空间的,让树的高度尽可能的矮,最理想的情况,所有的树高度为2;
  • 具体做法是:find的时候,p即代表待查询的元素在集合中的位置,也是找待查询元素的根节点的一个游标,p作为游标是一直往树根移动的,每次找p的根节点的时候,只要游标p还没指向根节点,就让游标p指向的元素上移一层,然后游标p追到上移后的位置的父元素上,直到游标p追到根节点,此时,找到原p元素的根的同时,整棵树的层树也减少了,随着find操作的增多,这棵树最终是有可能变成高度只有2的树,从而完成路劲压缩;
  • 路劲压缩后,rank就无法准确的表示树的高度了,其只作为合并时的参考;
// 查找过程, 查找元素p所对应的集合编号
// O(h)复杂度, h为树的高度
private int find(int p){
    if(p < 0 || p >= parent.length)
        throw new IllegalArgumentException("p is out of bound.");

    while( p != parent[p] ){
        parent[p] = parent[parent[p]];
        p = parent[p];
    }
    return p;
}

性能测试

package _11._06;

import java.util.Random;

public class Main {

    private static double testUF(UF uf, int m){
        int size = uf.getSize();
        Random random = new Random();
        long startTime = System.nanoTime();


        for(int i = 0 ; i < m ; i ++){
            int a = random.nextInt(size);
            int b = random.nextInt(size);
            uf.unionElements(a, b);
        }

        for(int i = 0 ; i < m ; i ++){
            int a = random.nextInt(size);
            int b = random.nextInt(size);
            uf.isConnected(a, b);
        }

        long endTime = System.nanoTime();
        double time = (endTime - startTime) / 1000000000.0;
        return time;
    }

    public static void main(String[] args) {

        int size = 10000000;
        int m = 10000000;

        UnionFind3 uf3 = new UnionFind3(size);
        System.out.println("UnionFind3 : " + testUF(uf3, m) + " s");

        UnionFind4 uf4 = new UnionFind4(size);
        System.out.println("UnionFind4 : " + testUF(uf4, m) + " s");

        UnionFind5 uf5 = new UnionFind5(size);
        System.out.println("UnionFind5 : " + testUF(uf5, m) + " s");
    }
    
}

输出:

  • 有一定提升;

UnionFind3 : 5.7276717 s
UnionFind4 : 5.5825732 s
UnionFind5 : 4.5744065 s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值