并查集

81 阅读1分钟

用于将两个元素进行合并以及快速查找这两个元素是否属于一个集合。

主要由三个容器实现,elementMap里装的是每个元素,parentMap里装的是每个元素的顶级元素, sizeMap里装的是每个顶级元素的集合里元素数目。

JAVA代码实现:
package com.demo.unionFind;

import java.util.List;
import java.util.Map;
import java.util.Stack;

public class UnionFind {
    //并查集的元素
    public static class Node<V> {
        //数据
        public V val;

        //构造方法
        public Node(V val){
            this.val = val;
        }
    }

    //并查集类
    public static class UnionSet<V> {
        //并查集元素map
        public Map<V,Node<V>> elementMap;

        //并查集父亲节点map
        public Map<Node<V>,Node<V>> parentMap;

        //并查集大小map
        public Map<Node<V>,Integer> sizeMap;

        //构造方法
        public UnionSet(List<V> val){
            for (V v : val) {
                elementMap.put(v,new Node<V>(v));
                parentMap.put(new Node<V>(v),new Node<V>(v));
                sizeMap.put(new Node<V>(v),1);
            }
        }

        //找节点父亲,并打平化
        public Node<V> findFather(Node<V> node){
            Stack<Node<V>> stack = new Stack<Node<V>>();
            while (!(node == parentMap.get(node))){
                stack.push(node);
                node = parentMap.get(node);
            }

            while (!stack.isEmpty()){
                parentMap.put(stack.pop(),node);
            }
            return node;
        }

        //判断两个节点是否在一个集合中
        public boolean isSame(V v1,V v2){
            if(!elementMap.containsKey(v1) || !elementMap.containsKey(v2)){
                return false;
            }
            return findFather(elementMap.get(v1)) == findFather(elementMap.get(v2));
        }

        //合并两个节点
        public void union(V v1,V v2){
            if(!elementMap.containsKey(v1) || !elementMap.containsKey(v2)){
                return ;
            }
            Node<V> father1 = findFather(elementMap.get(v1));
            Node<V> father2 = findFather(elementMap.get(v2));

            if(father1 != father2){
                Integer size1 = sizeMap.get(father1);
                Integer size2 = sizeMap.get(father2);
                if(size1 >= size2){
                    parentMap.put(father2,father1);
                    sizeMap.put(father1,size1+size2);
                    sizeMap.remove(father2);
                }else{
                    parentMap.put(father1,father2);
                    sizeMap.put(father2,size1+size2);
                    sizeMap.remove(father1);
                }
            }
        }
    }
}