数据结构与算法 - 并查集

用途
  • 1.判断两个元素所在的集合是否是一个集合
  • 2.把两个元素所在的集合连接起来(union)
思路

用两个Map 一个存储节点以及他的父节点,另一个存储当前节点以及这个节点对应的集合的元素个数
实现第一个的时候有一个优化(路径压缩):在不断的查找父节点的时候,把每一个节点挂到整棵树的头节点上。在做两个集合连接的时候数据小的挂在数据大的后面。

/**
 * 并查集的基础
 * 1.判断两个集合是否是一个
 * 2.把两个元素所在的集合连接起来
 * @author zhx
 */
public class UnionFind {

    public static class Node{
        // 任意的结构
    }

    public static class UnionFindSet{
        public HashMap<Node, Node> fatherMap;
        public HashMap<Node, Integer> sizeMap;

        public UnionFindSet(List<Node> nodes){
            makeSets(nodes);
        }
        private void makeSets(List<Node> nodes){
            fatherMap = new HashMap<>();
            sizeMap = new HashMap<>();
            for (Node node:nodes) {
                fatherMap.put(node, node);
                sizeMap.put(node, 1);
            }
        }
        //思想就是不断的向上找直到遇到头节点,在这个过程中进行优化,把所有节点的父节点都设置为公共的最开始的父节点
        private Node findHead(Node node){
            Node father = fatherMap.get(node);
            if(father != node){
                father = findHead(father);
            }
            fatherMap.put(node, father);
            return father;
        }
        //判断两个点所在的结合是否是同一个集合
        private boolean isSameSet(Node a, Node b){
            return findHead(a) == findHead(b);
        }
        //把两个点所在的集合连接起来
        private void union(Node a, Node b){
            if(a == null || b == null){
                return;
            }
            Node aHead = findHead(a);
            Node bHead = findHead(b);
            if(aHead != bHead){
                int aSetSize = sizeMap.get(aHead);
                int bSetSize = sizeMap.get(bHead);
                if(aSetSize <= bSetSize){
                    fatherMap.put(aHead, bHead);
                    sizeMap.put(bHead, aSetSize + bSetSize);
                }else{
                    fatherMap.put(bHead, aHead);
                    sizeMap.put(aHead, aSetSize + bSetSize);
                }
            }

        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值