并查集基础概念与代码实现

并查集:

每个集都有一个节点作为该集合的代表,查两元素是否属于同个集合,只需对两元素顺着parent指针往上找,找到某节点其parent指针指向自己时停止,对比两元素的找到节点,如相同则两元素属于同个集合。

关键点:查询集合代表点且查到时,不着急返回该代表点,而是将沿途查上来的节点的parent指针修改为直接指向该集合代表点。

Union(A,B):A和B所在的集合合并。该操作会包含isSameSet操作。如不在同集合内,将大小较小的集合挂在较大的集合底下。

用并查集的前提:提前知道所有元素,将所有元素各自成一个集合

时间复杂度:不是每次查询的代价是O(1),而是查询次数很高或者合并次数很高时的平均代价会是O(1)

基础内容转载:https://zhuanlan.zhihu.com/p/93647900/

具体Code实现:

public static class node
    {
        
    }
    public static class UCS//Union checking set并查集
    {
        public HashMap<node, node>father;//存储父节点,key的父节点是value
        public HashMap<node, Integer>rank;//存储集合代表点所代表的集合的数量,非集合代表点对应的value忽视
        public UCS()
        {
            father = new HashMap<Union.node, Union.node>();
            rank = new HashMap<Union.node, Integer>();
        }
        public void makeset(List<node>nodesList)
        {
            //初始化数据,将数据打入哈希表中
            father.clear();
            rank.clear();
            for (node node : nodesList)
            {
                father.put(node, node);
                rank.put(node, 1);
            }
        }
        public node findFather(node n)
        {
            node F = father.get(n);
            if(F!=n)
                F = findFather(F);//往上寻找
            father.put(n, F);//把沿途的节点的父都直接指向找到的代表点F
            return F;
        }
        public void union(node a,node b)
        {
            if(a==null||b==null)
                return ;
            node aF = findFather(a);
            node bF = findFather(b);
            if(aF!=bF)
            {
                //对比两集合的大小,将小集合挂在大集合的代表点下,更新对应rank
                int aRank = rank.get(aF);
                int bRank = rank.get(bF);
                if(aRank<=bRank)
                {
                    father.put(aF, bF);
                    rank.put(bF, aRank+bRank);
                }
                else {
                    father.put(bF, aF);
                    rank.put(aF, aRank+bRank);
                }
            }
        }
    }
posted @ 2021-02-04 20:15  γGama  阅读(78)  评论(0编辑  收藏  举报