zoukankan      html  css  js  c++  java
  • 数据结构与算法分析 – Disjoint Set(并查集)

    什么是并查集?
    并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。

    并查集的主要操作
    1.合并两个不相交集合
    2.判断两个元素是否属于同一集合

    主要操作的解释及代码
    一开始我们假设元素都是分别属于一个独立的集合里的。
    (1).合并两个不相交集合 操作很简单:先设置一个数组Father[x],表示x的“父亲”的编号。 那么,合并两个不相交集合的方法就是,找到其中一个集合最父亲的父亲(也就是最久远的祖先),将另外一个集合的最久远的祖先的父亲指向它。
    Dis-Union.jpg

    上图为两个不相交集合,b图为合并后id(b)=id(g)

       1:  void init(){
       2:      int i;
       3:      for(i=0;i<maxn;i++)
       4:          id[i]=-1;
       5:  }
       6:  void Union(int x,int y){
       7:      int rx=find_root(x);
       8:      int ry=find_root(y);
       9:      if(rx==ry)
      10:          return;
      11:      id[ry]=rx;
      12:  }

    (2).判断两个元素是否属于同一集合仍然使用上面的数组,则本操作即可转换为寻找两个元素的最久远祖先是否相同。可以采用递归实现。

       1:  bool judge(int x, int y)
       2:  {
       3:      return find_root(x) == find_root(y);
       4:  }

    并查集的优化
    (1).路径压缩
    刚才我们说过,寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的。
    对此,我们必须要进行路径压缩,即我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面,这就是路径压缩了。

    路径压缩.jpg

       1:  int find_root(int x){
       2:      if(id[x]==-1)
       3:          return x;    
       4:      else
       5:          id[x]=find_root(id[x]);
       6:      return id[x];
       7:  }

    (2).rank合并
    1.按照树的高度合并。

       1:  int rank[N]={0};// 节点高度的上界 
       2:   
       3:  void Union(int x, int y)
       4:  {
       5:      int rx=find_root(x);
       6:      int ry=find_root(y);
       7:      if (rank[rx] > rank[ry])
       8:          id[ry] = rx;
       9:     else {
      10:          id[rx] = ry;
      11:          if (rank[rx] == rank[ry])
      12:              rank[ry]++;
      13:      }
      14:  }

    2.按照集合的大小合并

       1:  int rank[N];// 集合的大小
       2:   
       3:  void init(){
       4:  for(int i=0;i<N;i++){
       5:      id[i]=-1;
       6:      rank[i]=1;
       7:  }
       8:  void Union(int x, int y)
       9:  {
      10:      int rx=find_root(x);
      11:      int ry=find_root(y);
      12:      if (rank[rx] > rank[ry]){
      13:          rank[rx]+=rank[ry];
      14:          id[ry] = rx;
      15:      }
      16:     else {
      17:          rank[ry]+=rank[rx];
      18:          id[rx] = ry;
      19:      }
      20:  }

    并查集系列题目[HDU]:http://acm.hdu.edu.cn/problemclass.php?id=721

  • 相关阅读:
    怎么往mac中finder个人收藏里添加文件夹
    UIView 动画
    添加.pch文件
    声明属性的关键字
    创建app前的环境配置/AppIcon/启动图片
    修改动画的旋转支点
    实现自定义xib和storyboard的加载,
    Quartz2D绘图 及实例:下载进度
    帧动画
    在职研究生第一单元第二单元第三单元第四单元是什么?
  • 原文地址:https://www.cnblogs.com/ZJUT-jiangnan/p/3561766.html
Copyright © 2011-2022 走看看