zoukankan      html  css  js  c++  java
  • 并查集

      并查集是一种使用树形结构处理集合问题的数据结构,从它的名字可以看出,并查集支持集合的合并、集合的查询两种功能。并查集的概念很好理解,下面对并查集进行简单举例。

      一个学校有10名学生,学生的学号分别从1~10,这10名学生被随机分在了4个 班,具体分班情况如下:

      0号班:学号为1、3、4的 学生,

      1号班:学号为2、5、6、7、8的学生,

      2号班:学号为10的学生,

      3号班:学号为9的学生。

    为了对以上分班情况进行存储,可以使用如下数组进行记录:

    0 1 0 0 1 1 1 1 3 2

     

      数组下标用来表示学号,数组下标对应的元素用来存储该学生所在的班级编号,实现过程如下:

      

    const int MAX = 1001;
    int f[MAX];

      此时,如果要对0号班级和1号班级的学生进行合并,只需要遍历一遍数组将全部的1改为0或者将全部的0改为1。这个操作的时间复杂度为O(n),这是一个很慢的速度,从构建数据结构的角度出发,可以对其进行优化。

      我们将学生与班级之间的隶属关系从线性结构转化为二维树形结构,父亲节点为班级编号,儿子节点为学生编号。此时,对于10名学生和4个班级之间的关系,可以转化为如下形式:

      

      

      当要求将0班和1班合并,只需将0节点变成1节点的儿子节点,合并操作由于只需要设置父子关系,因此时间复杂度为O(1),合并后如下:

      

      当要求对所属集合进行查询时,,只需沿着父亲不断找到根。比如说要求查询合并后4号学生所属班级,查询过程为:先找到4号学生的父亲节点0班,再找到0班的父亲节点1班,所以4号学生属于1班。由于查询过程需要不断往上查找根,因此时间复杂度为O(N),查询操作的此处可以进一步优化。

      我们使用路径压缩来对查询过程进行优化。

      所谓路径压缩,是指在查找根时同时更新路径上所有节点的根,这样可以使得均摊时间复杂度降低至O(1)。我们使用递归来完成这一操作,递归实现过程如下:

      

    void findF(int now)
    {
        if(f[now] == now) return now;
        f[now] = findF(f[now]);  //更新路径上的节点
        return f[now];
    }

      

      上面提到的集合合并操作实现过程如下:

      

    void  mergeS(int x, int y)   
    {
        int fx = findF(x);   //x的父亲节点       
        int fy = findF(y);   //y的父亲节点
        f[fx] = fy;     //将x所在的集合合并到y所在的集合下面
    }

      完美结束。

  • 相关阅读:
    Python打包方法——Pyinstaller
    在线检测显示器屏幕尺寸
    python_分布式进程中遇到的问题
    软件测试面试题(一)
    Django在根据models生成数据库表时报 __init__() missing 1 required positional argument: 'on_delete'
    mac系统 安装 IPython
    京东自动抢茅台脚本 Python
    CMake使用总结(一)
    小白安装eclipse插件—>testNG
    离线安装eclipse-testNG插件
  • 原文地址:https://www.cnblogs.com/potapo/p/9348542.html
Copyright © 2011-2022 走看看