并查集

 

package newcoder;

import java.util.HashMap;
import java.util.List;
import java.util.Stack;

public class UnionFind {

    public static class Element<V> {
        public V value;
        
        public Element (V value) {
            this.value = value;
        }
    }
    
    public static class UnionFindSet<V> {
        /**
         * 根据用户的value映射为包装类
         */
        public HashMap<V, Element<V>> elementMap;
        /**
         * 每个element都有自己的parent,代表节点的parent为自己
         */
        public HashMap<Element<V>, Element<V>> parentMap;
        /**
         * 每个代表节点代表了多少节点(如果不是代表节点,则为0)
         */
        public HashMap<Element<V>, Integer> sizeMap;
        
        /**
         * 初始化操作
         */
        public UnionFindSet(List<V> list) {
            elementMap = new HashMap<>();
            parentMap = new HashMap<>();
            sizeMap = new HashMap<>();
            
            for (V v : list) {
                Element<V> ele = new Element<V>(v);
                elementMap.put(v, ele);
                parentMap.put(ele, ele);
                sizeMap.put(ele, 1);
            }
        }
        
        /**
         * 方法1:判断两个节点是否为同一个集合
         */
        public boolean isSameSet(V a, V b) {
            if(elementMap.containsKey(a) && elementMap.containsKey(b)) {
                return findHead(elementMap.get(a)) == findHead(elementMap.get(b));
            }
            return false;
        }
        
        /**
         * 方法2:合并两个元素
         * @param a
         * @param b
         */
        public void union(V a, V b) {
            if(elementMap.containsKey(a) && elementMap.containsKey(b)) {
                Element<V> aHead = findHead(elementMap.get(a));
                Element<V> bHead = findHead(elementMap.get(b));
                if(aHead != bHead) {
                    Element<V> big = sizeMap.get(aHead) > sizeMap.get(bHead) ? aHead : bHead;
                    Element<V> small = big == aHead ? bHead : aHead;
                    parentMap.put(small, big);
                    sizeMap.put(big, sizeMap.get(big) + sizeMap.get(small));
                    sizeMap.remove(small);
                }
            }
        }
        
        /**
         * 私有方法:获取代表节点并将节点扁平化
         * @param ele
         * @return
         */
        private Element<V> findHead(Element<V> ele) {
             Stack<Element<V>> stack = new Stack<>();
             while(ele != parentMap.get(ele)) {
                 stack.push(ele);
                 ele = parentMap.get(ele);
             }
             
             while(!stack.isEmpty()) {
                 parentMap.put(stack.pop(), ele);
             }
             return ele;     
        }
    }
    
}

 

posted @ 2019-09-25 14:54  莹狼  阅读(102)  评论(0编辑  收藏  举报