Skip to content

Commit

Permalink
feat 并查集
Browse files Browse the repository at this point in the history
  • Loading branch information
tianbin committed Nov 2, 2022
1 parent 20f702a commit dd31564
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 30 deletions.
16 changes: 16 additions & 0 deletions src/main/java/data_struct/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package data_struct;

/**
* Created by nibnait on 2022/11/02
*/
public class Node<T> {
public T value;

public Node(T v) {
value = v;
}

public static <T> Node v(T v) {
return new Node(v);
}
}
51 changes: 22 additions & 29 deletions src/main/java/data_struct/ds1_堆/HeapGreater.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,40 +24,32 @@ 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;
System.out.println(p.getAge());
}
}

private class MyComparator implements Comparator<Inner> {
private class MyComparator implements Comparator<Node> {

@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<T> {
public T value;
public class MaxHeapGreater implements MyHeap<Node> {

public Inner(T v) {
value = v;
}
}

public class MaxHeapGreater implements MyHeap<Inner> {

private ArrayList<Inner> heap;
private HashMap<Inner, Integer> indexMap;
private ArrayList<Node> heap;
private HashMap<Node, Integer> indexMap;
private int heapSize;
private Comparator<? super Inner> comparator;
private Comparator<? super Node> comparator;

public MaxHeapGreater(Comparator<? super Inner> comparator) {
public MaxHeapGreater(Comparator<? super Node> comparator) {
this.heap = new ArrayList<>();
this.indexMap = new HashMap<>();
this.heapSize = 0;
Expand All @@ -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++);
Expand All @@ -98,22 +91,22 @@ 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);
indexMap.put(o1, 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);
Expand Down Expand Up @@ -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) {
Expand All @@ -159,17 +152,17 @@ public void remove(Inner obj) {
}

@Override
public void resign(Inner obj) {
public void resign(Node obj) {
Integer index = indexMap.get(obj);

heapInsert(index);
sinkDown(index);
}

@Override
public List<Inner> getAllElements() {
List<Inner> allElements = new ArrayList<>();
for (Inner e : heap) {
public List<Node> getAllElements() {
List<Node> allElements = new ArrayList<>();
for (Node e : heap) {
allElements.add(e);
}
return allElements;
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/data_struct/ds3_并查集/MyUnionFind.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package data_struct.ds3_并查集;

/**
* Created by nibnait on 2022/11/02
*/
public interface MyUnionFind<T> {

/**
* 找到 当前节点 的代表节点
*/
T findAncestor(T cur);

/**
* 是否在同一个集合内
*/
boolean isSameSet(T a, T b);

/**
* 把 a 节点,并入 b 节点所在集合中
*/
void union(T a, T b);

/**
* 当前一共有多少个集合
*/
int size();
}
119 changes: 119 additions & 0 deletions src/main/java/data_struct/ds3_并查集/UnionFind.java
Original file line number Diff line number Diff line change
@@ -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<Node> {

// 存放节点对应的直系父亲节点
private Map<Node, Node> fathers;
// 存放 祖先节点 对应的集合的大小。
private Map<Node, Integer> sizeMap;

public UnionFindImpl(List<Node> 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<Node> 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Master 公式:
- 如果 log(b,a) == d, 复杂度为 O(N^d * logN)

### 堆 和 加强堆
[堆相关](../../../data_struct/)
[堆相关](../../../java/data_struct/ds1_堆)

### 排序算法总结

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 并查集
[并查集 数据结构](../../../java/data_struct/ds3_并查集)

0 comments on commit dd31564

Please sign in to comment.