From dd31564dba359dc6bb713d9e59eca6d89dd5b412 Mon Sep 17 00:00:00 2001 From: tianbin Date: Wed, 2 Nov 2022 09:28:26 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=B9=B6=E6=9F=A5=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/data_struct/Node.java | 16 +++ .../ds1_\345\240\206/HeapGreater.java" | 51 ++++---- .../MyUnionFind.java" | 27 ++++ .../UnionFind.java" | 119 ++++++++++++++++++ ...00\347\232\204\347\256\227\346\263\225.md" | 2 +- ...x_\345\271\266\346\237\245\351\233\206.md" | 3 + 6 files changed, 188 insertions(+), 30 deletions(-) create mode 100644 src/main/java/data_struct/Node.java create mode 100644 "src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/MyUnionFind.java" create mode 100644 "src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/UnionFind.java" create mode 100644 "src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c04xx_\345\271\266\346\237\245\351\233\206.md" diff --git a/src/main/java/data_struct/Node.java b/src/main/java/data_struct/Node.java new file mode 100644 index 00000000..f401816c --- /dev/null +++ b/src/main/java/data_struct/Node.java @@ -0,0 +1,16 @@ +package data_struct; + +/** + * Created by nibnait on 2022/11/02 + */ +public class Node { + public T value; + + public Node(T v) { + value = v; + } + + public static Node v(T v) { + return new Node(v); + } +} diff --git "a/src/main/java/data_struct/ds1_\345\240\206/HeapGreater.java" "b/src/main/java/data_struct/ds1_\345\240\206/HeapGreater.java" index 1a13fb64..854ba63e 100644 --- "a/src/main/java/data_struct/ds1_\345\240\206/HeapGreater.java" +++ "b/src/main/java/data_struct/ds1_\345\240\206/HeapGreater.java" @@ -3,6 +3,7 @@ import common.model.Person; import common.util.SysOut; import common.util.SysRandom; +import data_struct.Node; import org.junit.Test; import java.util.ArrayList; @@ -23,7 +24,7 @@ public void testCase() { int limit = 10; MaxHeapGreater maxHeap = new MaxHeapGreater(new MyComparator()); for (int i : arr) { - maxHeap.push(new Inner(Person.buildByAge(i))); + maxHeap.push(new Node(Person.buildByAge(i))); } for (int i = 0; i < limit; i++) { Person p = (Person) maxHeap.pop().value; @@ -31,32 +32,24 @@ public void testCase() { } } - private class MyComparator implements Comparator { + private class MyComparator implements Comparator { @Override - public int compare(Inner o1, Inner o2) { + public int compare(Node o1, Node o2) { Person p1 = (Person) o1.value; Person p2 = (Person) o2.value; return p1.getAge() - p2.getAge(); } } - public class Inner { - public T value; + public class MaxHeapGreater implements MyHeap { - public Inner(T v) { - value = v; - } - } - - public class MaxHeapGreater implements MyHeap { - - private ArrayList heap; - private HashMap indexMap; + private ArrayList heap; + private HashMap indexMap; private int heapSize; - private Comparator comparator; + private Comparator comparator; - public MaxHeapGreater(Comparator comparator) { + public MaxHeapGreater(Comparator comparator) { this.heap = new ArrayList<>(); this.indexMap = new HashMap<>(); this.heapSize = 0; @@ -74,12 +67,12 @@ public boolean isFull() { } @Override - public boolean contains(Inner obj) { + public boolean contains(Node obj) { return indexMap.containsKey(obj); } @Override - public void push(Inner obj) { + public void push(Node obj) { heap.add(obj); heapInsert(heapSize++); @@ -98,8 +91,8 @@ private void heapInsert(int curIndex) { } private void swap(int i, int j) { - Inner o1 = heap.get(i); - Inner o2 = heap.get(j); + Node o1 = heap.get(i); + Node o2 = heap.get(j); heap.set(i, o2); heap.set(j, o1); indexMap.put(o2, i); @@ -107,13 +100,13 @@ private void swap(int i, int j) { } @Override - public Inner peek() { + public Node peek() { return heap.get(0); } @Override - public Inner pop() { - Inner heap0 = heap.get(0); + public Node pop() { + Node heap0 = heap.get(0); swap(0, heapSize - 1); heap.remove(--heapSize); indexMap.remove(heap0); @@ -141,11 +134,11 @@ private void sinkDown(int curIndex) { } @Override - public void remove(Inner obj) { + public void remove(Node obj) { Integer index = indexMap.get(obj); indexMap.remove(obj); - Inner replace = heap.get(heapSize - 1); + Node replace = heap.get(heapSize - 1); heap.remove(--heapSize); if (comparator.compare(obj, replace) == 0) { @@ -159,7 +152,7 @@ public void remove(Inner obj) { } @Override - public void resign(Inner obj) { + public void resign(Node obj) { Integer index = indexMap.get(obj); heapInsert(index); @@ -167,9 +160,9 @@ public void resign(Inner obj) { } @Override - public List getAllElements() { - List allElements = new ArrayList<>(); - for (Inner e : heap) { + public List getAllElements() { + List allElements = new ArrayList<>(); + for (Node e : heap) { allElements.add(e); } return allElements; diff --git "a/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/MyUnionFind.java" "b/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/MyUnionFind.java" new file mode 100644 index 00000000..c5836ec9 --- /dev/null +++ "b/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/MyUnionFind.java" @@ -0,0 +1,27 @@ +package data_struct.ds3_并查集; + +/** + * Created by nibnait on 2022/11/02 + */ +public interface MyUnionFind { + + /** + * 找到 当前节点 的代表节点 + */ + T findAncestor(T cur); + + /** + * 是否在同一个集合内 + */ + boolean isSameSet(T a, T b); + + /** + * 把 a 节点,并入 b 节点所在集合中 + */ + void union(T a, T b); + + /** + * 当前一共有多少个集合 + */ + int size(); +} diff --git "a/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/UnionFind.java" "b/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/UnionFind.java" new file mode 100644 index 00000000..1fa0c366 --- /dev/null +++ "b/src/main/java/data_struct/ds3_\345\271\266\346\237\245\351\233\206/UnionFind.java" @@ -0,0 +1,119 @@ +package data_struct.ds3_并查集; + +import com.google.common.collect.Lists; +import data_struct.Node; +import org.apache.commons.collections4.CollectionUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +/** + * Created by nibnait on 2022/11/02 + */ +public class UnionFind { + + @Test + public void testCase() { + + Node node1 = Node.v(1); + Node node2 = Node.v(2); + Node node3 = Node.v(3); + Node node4 = Node.v(4); + Node node5 = Node.v(5); + + UnionFindImpl unionFind = new UnionFindImpl(Lists.newArrayList(node1, node2, node3, node4, node5)); + Assert.assertEquals(5, unionFind.size()); + Assert.assertFalse(unionFind.isSameSet(node1, node2)); + Assert.assertEquals(node1, unionFind.findAncestor(node1)); + + unionFind.union(node1, node2); + Assert.assertTrue(unionFind.isSameSet(node1, node2)); + Assert.assertEquals(4, unionFind.size()); + Assert.assertEquals(node1, unionFind.findAncestor(node2)); + + unionFind.union(node3, node4); + Assert.assertEquals(3, unionFind.size()); + Assert.assertEquals(node3, unionFind.findAncestor(node4)); + + unionFind.union(node1, node5); + Assert.assertEquals(2, unionFind.size()); + + unionFind.union(node2, node4); + Assert.assertEquals(node1, unionFind.findAncestor(node4)); + + } + + public class UnionFindImpl implements MyUnionFind { + + // 存放节点对应的直系父亲节点 + private Map fathers; + // 存放 祖先节点 对应的集合的大小。 + private Map sizeMap; + + public UnionFindImpl(List nodes) { + fathers = new HashMap<>(); + sizeMap = new HashMap<>(); + if (CollectionUtils.isEmpty(nodes)) { + return; + } + for (Node node : nodes) { + fathers.put(node, node); + sizeMap.put(node, 1); + } + } + + /** + * 优化点1:为了每次往上找的链 都能更短一点。 + * 可以找完之后把这一串节点全部打平,直接挂在 ancestor 下面 + */ + @Override + public Node findAncestor(Node cur) { + Stack stack = new Stack<>(); + while (cur != fathers.get(cur)) { + stack.push(cur); + cur = fathers.get(cur); + } + + while (!stack.isEmpty()) { + Node node = stack.pop(); + fathers.put(node, cur); + } + return cur; + } + + @Override + public boolean isSameSet(Node a, Node b) { + return findAncestor(a) == findAncestor(b); + } + + /** + * 优化点2:为了链的长度涨的慢一点。 + * 可以小集合的头节点 往大集合上挂。 + */ + @Override + public void union(Node a, Node b) { + Node aHead = findAncestor(a); + Node bHead = findAncestor(b); + if (aHead == bHead) { + return; + } + + Integer aSize = sizeMap.get(aHead); + Integer bSize = sizeMap.get(bHead); + Node big = aSize >= bSize ? aHead : bHead; + Node small = big == aHead ? bHead : aHead; + fathers.put(small, big); + sizeMap.put(big, aSize + bSize); + sizeMap.remove(small); + } + + @Override + public int size() { + return sizeMap.size(); + } + } +} diff --git "a/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c01xx_\344\270\200\344\272\233\350\266\205\347\272\247\345\237\272\347\241\200\347\232\204\347\256\227\346\263\225.md" "b/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c01xx_\344\270\200\344\272\233\350\266\205\347\272\247\345\237\272\347\241\200\347\232\204\347\256\227\346\263\225.md" index 27321f08..01468695 100644 --- "a/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c01xx_\344\270\200\344\272\233\350\266\205\347\272\247\345\237\272\347\241\200\347\232\204\347\256\227\346\263\225.md" +++ "b/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c01xx_\344\270\200\344\272\233\350\266\205\347\272\247\345\237\272\347\241\200\347\232\204\347\256\227\346\263\225.md" @@ -8,7 +8,7 @@ Master 公式: - 如果 log(b,a) == d, 复杂度为 O(N^d * logN) ### 堆 和 加强堆 -[堆相关](../../../data_struct/堆) +[堆相关](../../../java/data_struct/ds1_堆) ### 排序算法总结 diff --git "a/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c04xx_\345\271\266\346\237\245\351\233\206.md" "b/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c04xx_\345\271\266\346\237\245\351\233\206.md" new file mode 100644 index 00000000..6ab5e92a --- /dev/null +++ "b/src/main/test/algorithmzuo/b_\344\275\223\347\263\273\345\255\246\344\271\240\347\217\255/c04xx_\345\271\266\346\237\245\351\233\206.md" @@ -0,0 +1,3 @@ +## 并查集 +[并查集 数据结构](../../../java/data_struct/ds3_并查集) +