用途
- 1.判断两个元素所在的集合是否是一个集合
- 2.把两个元素所在的集合连接起来(union)
思路
用两个Map 一个存储节点以及他的父节点,另一个存储当前节点以及这个节点对应的集合的元素个数
实现第一个的时候有一个优化(路径压缩):在不断的查找父节点的时候,把每一个节点挂到整棵树的头节点上。在做两个集合连接的时候数据小的挂在数据大的后面。
/**
* 并查集的基础
* 1.判断两个集合是否是一个
* 2.把两个元素所在的集合连接起来
* @author zhx
*/
public class UnionFind {
public static class Node{
// 任意的结构
}
public static class UnionFindSet{
public HashMap<Node, Node> fatherMap;
public HashMap<Node, Integer> sizeMap;
public UnionFindSet(List<Node> nodes){
makeSets(nodes);
}
private void makeSets(List<Node> nodes){
fatherMap = new HashMap<>();
sizeMap = new HashMap<>();
for (Node node:nodes) {
fatherMap.put(node, node);
sizeMap.put(node, 1);
}
}
//思想就是不断的向上找直到遇到头节点,在这个过程中进行优化,把所有节点的父节点都设置为公共的最开始的父节点
private Node findHead(Node node){
Node father = fatherMap.get(node);
if(father != node){
father = findHead(father);
}
fatherMap.put(node, father);
return father;
}
//判断两个点所在的结合是否是同一个集合
private boolean isSameSet(Node a, Node b){
return findHead(a) == findHead(b);
}
//把两个点所在的集合连接起来
private void union(Node a, Node b){
if(a == null || b == null){
return;
}
Node aHead = findHead(a);
Node bHead = findHead(b);
if(aHead != bHead){
int aSetSize = sizeMap.get(aHead);
int bSetSize = sizeMap.get(bHead);
if(aSetSize <= bSetSize){
fatherMap.put(aHead, bHead);
sizeMap.put(bHead, aSetSize + bSetSize);
}else{
fatherMap.put(bHead, aHead);
sizeMap.put(aHead, aSetSize + bSetSize);
}
}
}
}
}