并查集的结构实现

并查集的结构实现,对外提供两个方法:
1.检查两个元素是否属于一个集合
2.将两个元素所在的集合合并在一起

下面这个图是并查集的结构类似图,就是一颗多叉树

结点的合并图
并查集的结构优化 “扁平”

public static class UnionFindSetr{
  private HashMap<node,node> fatherMap;//前面的node就是某一个结点,后面的node就是这个结点的父节点
  private HashMap<node,Integer> sizeMap;//某一个结点他所在的集合有多少个结点。integer代表的是node所在的集合的属性。
  
  public UnionFindSetr(LinkedList<node> nodes){
   fatherMap = new HashMap<node,node>();
   sizeMap = new HashMap<node,Integer>();
   makeSet(nodes);
  }
  
  private void makeSet(LinkedList<node> nodes) {
   for (node node : nodes) {//刚开始是每一个点自己成为一个集合
    fatherMap.put(node, node);
    sizeMap.put(node, 1);
   }
  }
  
  //找头,给一个元素把他的代表结点返回,并且在这个过程中把链压缩变扁平。递归
  private node getHead(node node) {
   node father = fatherMap.get(node);
   if(father != node) {
    father = getHead(father);
   }
   return father;
  }

  //找头,给一个元素把他的代表结点返回,并且在这个过程中把链压缩变扁平。非递归
  private node getHead1(node node) {
   Stack<node> stack = new Stack<node>();
   node cur = node;
   node parent = fatherMap.get(cur);
   while(cur != parent) {
    stack.push(cur);//每次压入当前的结点
    cur = parent;
    parent = fatherMap.get(cur);
   }
   while(!stack.isEmpty()) {
    fatherMap.put(stack.pop(), parent);
   }
   return parent;
  }

  
  //判断两个结点是不是同一个集合,只需要比较他们的集合的代表结点是不是同一个
  public boolean isSameSet(node a ,node b) {
   return getHead(a) == getHead(b);
  }
  
  //将两个元素所在的集合合并在一起,我们规定小的往大的上面挂(这个是随便的看自己的定义了)
  public void union(node a,node b) {
   if(a == null && b == null) {
    return ;
   }
   node aHead = fatherMap.get(a);
   node bHead = fatherMap.get(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);
    }
   }
  }
 }

下面是一个大佬总结的并查集基础用法,引用一下

https://blog.csdn.net/xianpingping/article/details/80011187

结论:一共的数据样本假设有n个,可以随意的查两个元素在一个集合,也可以任意的把两个元素所在的集合合并,只要查询次数+合并次数整体逼近了O(N)及以上,那么单次的操作不管查询还是合并的平均时间复杂度都是O(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值