并查集用于解决关联性问题,可以合并不同的集合,判断是否属于同一集合. 根据业务场景应用很广,比如是否属于同一省份,或根据不同信息判定是否属于同一个人...
并查集结构: 如下UnionSet 结构
**
* 并查集的结构的重要性,解决一切联通性的问题,是不是同一个用户,是否属于同一个集合
*/
public class UnionSetFind {
public static void main(String[] args) {
Integer[] arr = {1,3,4,5,6,7};
UnionSet<Integer> union = new UnionSet<>(arr);
union.union(4,5);
System.out.println(union.isSameSet(4, 6));//false
System.out.println(union.isSameSet(4, 5));//true
}
//定义并查集结构
private static class UnionSet<V> {
//元素的值及对应的节点
public HashMap<V, Node<V>> nodes;
//每个元素与其对应的父节点
public HashMap<Node<V>, Node<V>> parents;
//集合size,key是集合的代表,即能标识一个集合体的代表
public HashMap<Node<V>, Integer> sizeMap;
//初始化后所有的节点都是独立的集合
public UnionSet(V[] values) {
this.nodes = new HashMap<>();
this.parents = new HashMap<>();
this.sizeMap = new HashMap<>();
for (V v : values) {
Node<V> node = new Node<>(v);
this.nodes.put(v, node);
this.parents.put(node, node);
this.sizeMap.put(node, 1);
}
}
//findFather查找父节点,查找时优化使链变得扁平
private Node<V> getFather(Node<V> node) {
if(!parents.containsKey(node)){
return null;
}
Stack<Node<V>> stack = new Stack<>();
Node<V> curr = node;
while (curr != parents.get(curr)){
//包括子节点在内都扁平化处理,压入栈中
stack.push(curr);
curr = parents.get(curr);
}
//扁平化,操作逐渐趋近O(1)
while (!stack.empty()){
parents.put(stack.pop(),curr);
}
return curr;
}
//union时将小set挂到大
public void union(V left, V right) {
if(!nodes.containsKey(left) || !nodes.containsKey(right)){
return;
}
Node<V> lhead = getFather(nodes.get(left));
Node<V> rhead = getFather(nodes.get(right));
if(lhead != rhead){
int lsize = sizeMap.get(lhead);
int rsize = sizeMap.get(rhead);
Node<V> big = lsize < rsize ? rhead : lhead;
Node<V> small = big == rhead ? lhead : rhead;
parents.put(small,big);
sizeMap.remove(small);
sizeMap.put(big,sizeMap.get(big)+rsize);
}
}
//是否是同一个集合
public boolean isSameSet(V v1, V v2) {
if (!nodes.containsKey(v1) || !nodes.containsKey(v2)) {
return false;
}
return getFather(nodes.get(v1)) == getFather(nodes.get(v2));
}
}
//将要存储的数据封装为一个节点,供parent这个map使用
private static class Node<V> {
public V v;
public Node(V v) {
this.v = v;
}
}
}
?左神算法学习
|