diff --git a/src/ds/picture/UnionFind.java b/src/ds/picture/UnionFind.java new file mode 100644 index 0000000..40ab6f2 --- /dev/null +++ b/src/ds/picture/UnionFind.java @@ -0,0 +1,85 @@ +package ds.picture; + +import java.util.HashMap; +import java.util.List; +import java.util.Stack; + +/** + * 并查集 + * @author Wen + * @date 2022/9/7 23:27 + */ +public class UnionFind { + //集合结构体 + static class Node { + T t; + + public Node(T t) { + this.t = t; + } + } + + static class UnionFindSet { + + //自身代表点指向集合 + private HashMap> nodeHashMap; + //每个结构体上层指向存储 + private HashMap, Node> parentMap; + //代表结构体的总节点数 + private HashMap, Integer> sizeMap; + + + public UnionFindSet(List iterator) { + int size = iterator.size(); + nodeHashMap = new HashMap<>(size); + parentMap = new HashMap<>(size); + sizeMap = new HashMap<>(size); + for (V v : iterator) { + Node node = new Node<>(v); + nodeHashMap.put(v, node); + parentMap.put(node, node); + sizeMap.put(node, 1); + } + } + + //找代表节点 + public Node findFather(Node cur) { + Stack> stack = new Stack<>(); + while (parentMap.get(cur) != cur) { + stack.push(cur); + cur = parentMap.get(cur); + } + //将从cur出发的链压平,所经过的节点的代表节点都是cur的代表节点 + while (!stack.isEmpty()) { + parentMap.put(stack.pop(), cur); + } + return cur; + } + + //是否拥有同一个代表结点 + public boolean isSameSet(V a, V b) { + if (nodeHashMap.get(a) == null || nodeHashMap.get(b) == null) { + return false; + } + return findFather(nodeHashMap.get(a)) == findFather(nodeHashMap.get(b)); + } + + //将小集合合并到大集合 + public void union(V a, V b) { + if (nodeHashMap.get(a) == null || nodeHashMap.get(b) == null) { + return; + } + Node aHead = findFather(nodeHashMap.get(a)); + Node bHead = findFather(nodeHashMap.get(b)); + if (aHead != bHead) { + Node bigHead = sizeMap.get(aHead) > sizeMap.get(bHead) ? aHead : bHead; + Node smallHead = bigHead == aHead ? bHead : aHead; + parentMap.put(smallHead, bigHead); + sizeMap.put(bigHead, sizeMap.get(bigHead) + sizeMap.get(smallHead)); + sizeMap.remove(smallHead); + } + } + } + + +}