最近几日理了理学过的很多oi知识。。。发现不知不觉就有很多的知识忘记了。。。

在聊聊并查集的时候顺便当作巩固吧。。。。

什么是并查集呢?

( Union Find Set ) 是一种用于处理分离集合的抽象数据结构类型。

具体一点:

  当我们给出两个元素的一个无序对(a,b)时,需要快速合并a和b所在的集合,这期间需要反复查找出某元素所在的集合,“并”、“查”和“集”三字由此而来。也就是说,并查集的作用是动态地维护和处理集合元素之间的复杂关系。

  在并查集中,n个不同的元素被分为若干组,每组是一个集合,这种集合就叫做“分离集合”。并查集支持查找一个元素所属的集合以及两个元素各自所属集合的合并操作。

例如,我们有这样一个问题:

  一个城镇里居住着n个市民,已知一些人互为朋友,而且朋友的朋友也是朋友,也就是说,如果A和B是朋友,C和B是朋友,则A和C也是朋友,请你根据给出的若干组朋友关系,求出最大的一个朋友圈的人数。

  这就有了并查集的用武之地了,一开始我们把所有人都各自放在一个集合中,然后根据依次给出的朋友关系,查找判断两个人是否属于同一个集合(是否已经是朋友),如果不在同一个集合,则将这两个集合合并成一个集合(行成一个朋友圈),最后看哪个集合的元素最多并输出个数即可。

然而并查集有什么主要操作呢?

  使用并查集首先要记录一组分离的动态集合S = {S1,S2,···,Sn},每个集合还要设置一个代表来识别,代表只是要选择该集合中的某个元素即可,哪一个元素被选作代表是无所谓的,重要的是,如果请求某一动态集合的代表两次,且在两次请求间不修改集合,则两次得到的答案应该是相同的。并查集主要有三种操作:初始化、查找与合并。

  (1)初始化:make-set(x)

  建立一个新的集合,其仅有的成员是x(同时就是代表)。由于各集合是分离的,所以要求x在没有其他集合中出现过。使用并查集前都需要执行一次初始化操作,无论采用何种实现方式,其时间复杂度都是O(n)。

  (2)查找:find-set(x)

  查找一个元素所在的集合,本操作返回一个包含x的集合的代表。查找是并查集的核心操作,也是优化并查集效率的重点。

  (3)合并:merge(x,y)

  将包含x和y的动态集合(假设为Sx和Sy)合并成一个新的集合S,本操作返回集合Sx∪Sy的代表。一般来说,在不同的实现中通常以Sx或者Sy的代表作为新集合的代表。合并之前一般要先判断两个元素是否属于同一集合,这可以通过查找操作来实现。

终于到了并查集的实现了!!

  并查集可以采用数组、链表和树三种数据结构来实现,选择不同的实现方式会给查找操作和合并操作的效率带来很大的差别。

并查集的数组实现:

  实现并查集的最简单的方法就是用数组记录每个元素所属集合的编号,A[i] = j 表示元素i属于第j 类集合,初始化A[i] = i。查找元素所属的集合时,只需读出数组中记录的该元素所属集合的编号A[i],时间复杂度为O(1)。合并两个元素各自所属集合时,需要将数组中属于其中一个集合的元素所对应的数组元素值全部更新为另一个集合的编号值,时间复杂度为O(n)。所以用数组实现并查集是最简单的方法,而且容易理解,实际使用较多。但是,合并操作的代价太高,在最坏的情况下,所有集合合并成一个集合的总代价会达到O(n2)。

并查集的链表实现:

  用链表实现并查集也是一种很常见的手段。每个分离集合对应一个链表,链表有一个表头,每个元素有一个指针指向表头,表明了它所属集合的类别,另设一个指针指向它的下一个元素,同时为了方便实现,再设一个指针last表示链表的表尾。

  因为并查集问题处理的对象往往都是连续的整数,所以一般选择用静态数组来模拟链表,用下标对应集合的元素。具体数据结构体定义如下qwq:

struct node{int head,next,last;
}S[maxn];

  

  此时,初始化和查找操作的实现就很简单了。

make-set(x){S[x].head = x;S[x].next = 0;
}
find-set(x){return S[x].head;
}

  对于合并操作,我们先假设merge(x,y)的参数是有序的,是把y所属的集合合并到x所在的集合。首先执行查找操作,当出现find-set(x)≠ find-set(y)时,直接将y的表头接到x的表尾,同时将y所在集合的所有元素head值设为find-set(x),x的表尾也设为y的表尾。需要注意的是,last指针只要在表头结点中记录即可,因为每一次查找到find-set(x)都可以得到表头元素,而链表中其他元素记录last值是毫无意义的。

  考虑到输入数据的特殊性,根据以上合并方法,我们总是把y接到x后面,如果y所在的集合非常大,每次复制的代价就会非常高,比如输入数据形如:(2,1),(3,1),(4,1),·····,(n,1),显然y所在的集合就会越来越庞大,此时时间复杂度就会达到O(n2)。不过,我们可以很快滴想到一个优化方法:不妨比较x和y所在集合的大小,把较短的链表接在较长的链表尾部,这样效果是一样的,但时间效率肯定不比原来差。具体实现时可以在node里多设一个number域,用来记录此条链表中成员的个数。显然,number记录在表头元素中即可。将两个链表合并的时候,只需要将链表的number域相加,因此维护起来是非常方便的。这种快速实现的方法称为“加权启发式”合并,这里的权就是指number域。假设有n个元素,则可以证明这种方法合并操作的总次数不超过nlog2n次。

merge(x,y){x = find-set(x);y = find-set(y);if(x.number > y.number)merge(x,y);merge(y,x);
}

  

  以上是并查集的两种实现方法qwq。然而最最最重要以及实用的是并查集的树实现。我会在  谈一谈并查集QAQ(下) 中仔细讲解qwq。

  

转载于:https://www.cnblogs.com/excellent-zzy/p/10686911.html

谈一谈并查集QAQ(上)相关推荐

  1. poj 3728 The merchant// lca(倍增实现) + dp || tarjan+并查集路径上dp

    poj 3728 The merchant// lca(倍增实现) + dp Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: ...

  2. 【POJ - 1703】Find them, Catch them(带权并查集之--种类并查集 权为与父节点关系)

    题干: Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36176   Accep ...

  3. 算法:程序设计之并查集

    前言 之前一直都是听说并查集,感觉是一个神乎其技,狂拽酷炫.却没有想过在自己学习并查集之前,自已在解决问题的时候也能够想到一个和并查集异曲同工的方法.这个还是很愉快的. 版权说明 著作权归作者所有. ...

  4. 专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!

    文章目录 [JSOI2008]星球大战 In Touch 方格染色 Junk-Mail Filter [NOIP2010 提高组] 关押罪犯 Silver Woods Must Be Rectangu ...

  5. 数据结构 5-4-1 并查集

    一.概念 并查集本质上是对树的知识的利用,常用于集合的相关表示,不同于一般的二叉树,并查集用的是指向双亲节点的指针,便于分类而不便于找子节点, 二.代码实现 简单的并查集主要有三个函数,初始化.合并. ...

  6. 数据结构与算法(十二)并查集(Union Find)及时间复杂度分析

    本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化 Quick Find Quick Union 基于size的优化 基于rank的优化 路径压缩优化 并查集的时间复杂度 并查集的 ...

  7. 畅通工程 hdu 1232 HDU - 1863 (并查集+最小生成树)

    畅通工程hdu 1232 并查集 Problem Description Input Output 参考代码 HDU - 1863 Problem Description Input Output 参 ...

  8. 图 相关算法~从头学算法【广搜、 深搜、 拓扑排序、 并查集、 弗洛伊德算法、迪杰斯特拉算法】

    图的相关主流算法主要有: 广度优先搜索 深度优先搜索 拓扑排序 并查集 多源最短路径(弗洛伊德算法) 单源最短路径(迪杰斯特拉算法) 其中呢,最基本的是前两种,也就是平时常用的广搜和深搜,本文中将概要 ...

  9. 并查集(合并,查询)

    文章目录 简介: 模板 例题:食物链 源代码 实践并查集总结 简介: 并查集用于管理元素分组情况的数据结构,判断某一组合是否存在于同一集合(拥有同一性质) 树形结构实现但非二叉树,但是通过rank比较 ...

最新文章

  1. 文件流处理流式处理大数据处理
  2. BCH将于9月1日进行压力测试
  3. AJAX(二)jquery ajax
  4. Tomcat源码学习(4)-How Tomcat works(转)
  5. 电脑卡顿不流畅是什么原因_为什么安卓系统用久了会卡,苹果系统却依然流畅?原因找到了!...
  6. .NET Core运行时和基础类库性能提升
  7. python实现 Polar码极化过程
  8. 解读SSD目标检测方法
  9. 二维码生成器微信小程序源码
  10. Android 获取手机号码
  11. 下载xlsx文件打开一直提示文件已损坏
  12. 爬虫之模拟强智系统登录
  13. 找出符合要求的字符串子串
  14. tl wn322g linux驱动下载,TL-WN322G+驱动
  15. 海思lowlevel_init.S简单分析
  16. Theano官方文档的测试和总结(1):安装、基础语法、逻辑斯蒂回归
  17. 输入法编程相关资源汇集-欢迎补充
  18. 关于3B大战那点事儿
  19. Win10操作系统语言中文转英文设置步骤
  20. 如何删除.nfs00000xxxx文件

热门文章

  1. 如何解决Qt程序在其他电脑上无法运行的问题(Qt程序打包发布)
  2. sql 12天内的数据_想要在12周内成为数据科学家吗?
  3. ethtool编译与内核实现介绍
  4. 【Android 修炼手册】Gradle 篇 -- Gradle 的基本使用
  5. C++输入函数的应用
  6. 逾期了,如何消除不良记录?
  7. GNS3 VoIP Lab (Cisco 3725 and CME 4.3)
  8. 身体对腐朽灵魂的一次震撼:向京的雕塑与观众的行为
  9. 几张旧照片,用傻瓜拍的,翻出来凑数 (续)
  10. 数字图像处理技术详解程序_大学专业详解系列135——数字媒体技术(工学学士)...