• 并查集算法


      并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。(百度百科)

      解决并查集问题需要用到一种简单的数据结构——树:

      树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
    每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。(百度百科)
    注意:如果只有一个树只有一个节点,那么它本身就是自己的父节点。
     

    比如A的父节点是A,也是这个树的根节点,并且也是B和C的父节点;B和C是A的子节点。

      解决并查集问题分为三步:(1)初始化 (2)查询 (3)合并

      (1)初始化

      我们准备n个节点保存n个元素,编号1-n。最开始每个元素相护独立,没有任何联系,表现为n个孤立的节点。

    初始化代码:

    void Input(int N){
        for(int i = 0; i <= N; i++){
            F[i] = i;
        }
    }

      (2)查询

      查询的目的是为了检查两个节点是否属于一个组,我们沿着树向上走,如果可以走到同一个根节点,那么我们就认为这两个元素属于同一个组。相当于每个树的根节点就是这个树独一无二的特点,可以看到(找到)这个特点,它两就是一家人。

    查询代码:

    int Find(int x){
        return F[x] == x ? x : Find(F[x]);//先判断自己的根节点是不是自己,是返回x,不是继续查询父节点
    }

    但是这样效率比较低,在数据比较多,数字比较大时,可能会超时,那么我们可以把每个查询过的子节点和其根节点相连,构成只有两层的树结构,当再次查询是效率就会提升。可以进行路径压缩:

    路径压缩后代码如下:

    int Find(int x){
        return F[x] == x ? x : F[x] = Find(F[x]);/*先判断自己的根节点是不是自己,是返回x,不是便把它的父节点设为根节点*/

    }

      (3)合并

      若个查询到两个元素不是同一个组织,可以把它们进行合并。我们可以把其中甲方设置成为乙方的父节点便可,即其中甲方组织归属了乙方,它们的根节点相同。

    代码如下:

    void Union(int x, int y){
        int Fx = Find(x);
        int Fy = Find(y);
        if(Fx != Fy){ //判断连个元素是否属于一个树,若不是便把Fx设置成为Fy的父节点
            F[Fy] = Fx;
        }
    }
    种一棵树最好的时间是十年前,其次是现在。
  • 相关阅读:
    编写 unix和 windows的 Scala 脚本
    4种复制文件的方式性能比较
    Cacheable key collision with DefaultKeyGenerator
    Spring Cache 介绍
    Centos提示-bash: make: command not found的解决办法
    Scala的sealed关键字
    Groupby
    scala break & continue
    Scala implicit
    Scala可变长度参数
  • 原文地址:https://www.cnblogs.com/HyattXia/p/8366307.html
Copyright © 2020-2023  润新知