并查集最终版.ppt

上传人:zf 文档编号:30856441 上传时间:2024-03-23 格式:PPT 页数:56 大小:1.02MB
下载 相关 举报
并查集最终版.ppt_第1页
第1页 / 共56页
并查集最终版.ppt_第2页
第2页 / 共56页
并查集最终版.ppt_第3页
第3页 / 共56页
并查集最终版.ppt_第4页
第4页 / 共56页
并查集最终版.ppt_第5页
第5页 / 共56页
点击查看更多>>
下载资源
资源描述

并查集最终版.ppt

《并查集最终版.ppt》由会员分享,可在线阅读,更多相关《并查集最终版.ppt(56页珍藏版)》请在冰豆网上搜索。

并查集最终版.ppt

并并查集集JSOI2015JSOI2015冬令冬令营营u并查集基本概念并查集基本概念u并查集基本操作并查集基本操作u并查集应用举例并查集应用举例问题描述:

或许你并不知道,你的某个朋友是你的亲问题描述:

或许你并不知道,你的某个朋友是你的亲戚。

他可能是你的曾祖父的外公的女婿的外甥女的表戚。

他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子!

姐的孙子!

如果能得到完整的家谱,判断两个人是否亲戚应该如果能得到完整的家谱,判断两个人是否亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。

在这种情况下,最好的帮手就是计算机。

人力所能及。

在这种情况下,最好的帮手就是计算机。

为了将问题简化,你将得到一些亲戚关系的信息,如为了将问题简化,你将得到一些亲戚关系的信息,如MarryMarry和和TomTom是亲戚,是亲戚,TomTom和和BenBen是亲戚,等等。

从这些是亲戚,等等。

从这些信息中,你可以推出信息中,你可以推出MarryMarry和和BenBen是亲戚。

是亲戚。

例例1:

亲戚:

亲戚输入输入:

由两部分组成:

由两部分组成:

第一部分以第一部分以NN,MM开始。

开始。

NN为问题涉及的人的个数。

这为问题涉及的人的个数。

这些人的编号为些人的编号为1,2,3,1,2,3,N,N。

下面有。

下面有MM行,每行有两个数行,每行有两个数aaii,b,bii,表示已知,表示已知aaii和和bbii是亲戚。

是亲戚。

第二部分以第二部分以QQ开始。

以下开始。

以下QQ行有行有QQ个询问,每行为个询问,每行为ccii,ddii,表示询问,表示询问ccii和和ddii是否为亲戚。

是否为亲戚。

输出:

对于每个询问输出:

对于每个询问ccii,ddii,输出一行:

若,输出一行:

若ccii和和ddii为亲戚,为亲戚,则输出则输出“YesYes”,否则输出,否则输出“NoNo”。

请写一个程序,对于我们的关于亲戚关系的提请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

问,以最快的速度给出答案。

输入样例(输入样例(relation.inrelation.in):

):

10710724245757131389891212565623233334347107108989输出出样例(例(relation.outrelation.out):

):

YesYesNoNoYesYes问题规模问题规模1:

1N2551M10000001Q1000000各抒己见各抒己见思路点拔思路点拔u题意分析题意分析u算法及数据结构设计算法及数据结构设计u时间、空间复杂度估计及实践细节讨论时间、空间复杂度估计及实践细节讨论u优化思路讨论优化思路讨论输入入关关系系分离集合分离集合初始初始状状态1234567891012345678910(2,4)12,435678910(2,4)12,435678910(5,7)12,435,768910(5,7)12,435,768910(1,3)(1,3)1,32,45,7689101,32,45,768910(8,9)1,32,45,768,910(8,9)1,32,45,768,910(1,2)1,2,3,45,768,910(1,2)1,2,3,45,768,910(5,6)1,2,3,45,6,78,910(5,6)1,2,3,45,6,78,910(2,3)1,2,3,45,6,78,910(2,3)1,2,3,45,6,78,910集集合合定义及运算:

定义及运算:

varvars:

sets:

setof1.100;of1.100;集合与集合:

交集合与集合:

交A*BA*B、并、并A+BA+B、差、差A-BA-B,结果还是集合;,结果还是集合;关系运算关系运算相等相等=、不相等、不相等、包含于、包含于=,结果为,结果为booleanboolean;元素与集合:

元素与集合:

xinsxins,结果为,结果为booleanboolean;集合的优缺点:

容易理解,运算简单;集合的优缺点:

容易理解,运算简单;数据量小、调试不方便;数据量小、调试不方便;问题规模问题规模2:

1N200001M10000001Q1000000并查集并查集并查集(并查集(union-findsetunion-findset)是一种用于分离集合操作的抽)是一种用于分离集合操作的抽象数据类型。

它所处理的是象数据类型。

它所处理的是“集合集合”之间的关系,即动态地维之间的关系,即动态地维护和处理集合元素之间复杂的关系,当给出两个元素的一个无护和处理集合元素之间复杂的关系,当给出两个元素的一个无序对序对(a,ba,b)时,需要快速时,需要快速“合并合并”aa和和bb分别所在的集合,这其分别所在的集合,这其间需要反复间需要反复“查找查找”某个元素所在的集合。

某个元素所在的集合。

“并并”、“查查”和和“集集”三字由此而来。

在这种数据类型中,三字由此而来。

在这种数据类型中,nn个不同的元素被个不同的元素被分为若干组。

每组是一个集合,这种集合叫做分为若干组。

每组是一个集合,这种集合叫做分离集合分离集合(disjointsetdisjointset)。

并查集支持查找一个元素所属的集合以及)。

并查集支持查找一个元素所属的集合以及两个元素各自所属的集合的合并。

两个元素各自所属的集合的合并。

如何用已有的数据类型或数据结构去构造?

如何用已有的数据类型或数据结构去构造?

并查集本身不具有结构,必须借助一定的数据结并查集本身不具有结构,必须借助一定的数据结构以得到支持和实现。

构以得到支持和实现。

数据结构的选择是一个重要的数据结构的选择是一个重要的环节,选择不同的数据结构可能会在查找和合并的操环节,选择不同的数据结构可能会在查找和合并的操作效率上有很大的差别,但操作实现都比较简单高效。

作效率上有很大的差别,但操作实现都比较简单高效。

并查集的数据结构实现方法很多,一般用的比较多的并查集的数据结构实现方法很多,一般用的比较多的是,是,数组实现、链表实现和树实现数组实现、链表实现和树实现。

并查集并查集并查集的数据结构记录了一组分离的动态集合并查集的数据结构记录了一组分离的动态集合SS,S=S1,S2,S=S1,S2,SkSk,每个集合通过一个,每个集合通过一个“代表代表”加以识加以识别,代表即该集合中的某个元素(成员),哪一个成别,代表即该集合中的某个元素(成员),哪一个成员被选做代表是无所谓的,重要的是:

如果求某一动员被选做代表是无所谓的,重要的是:

如果求某一动态集合的代表两次,且在两次请求间不修改此集合,态集合的代表两次,且在两次请求间不修改此集合,则两次得到的答案应该是相同的。

则两次得到的答案应该是相同的。

动态集合中的每一元素是由一个对象来表示的,动态集合中的每一元素是由一个对象来表示的,设设xx表示一个对象,并查集的实现需要支持如下操作:

表示一个对象,并查集的实现需要支持如下操作:

并查集的基本操作并查集的基本操作MAKE-SETMAKE-SET(xx)建立一个新的集合,其仅有的成员(同时就是代表)是建立一个新的集合,其仅有的成员(同时就是代表)是xx。

由于各集合是分离的,所以要求由于各集合是分离的,所以要求xx没有在其它集合中出现过。

没有在其它集合中出现过。

UNIONUNION(x,yx,y)将包含将包含xx和和yy的动态集合(例如的动态集合(例如SxSx和和SySy)合并为一个新的集)合并为一个新的集合,假定在此操作前这两个集合是分离的。

结果的集合代表是合,假定在此操作前这两个集合是分离的。

结果的集合代表是SxSySxSy的某个成员。

一般来说,在不同的实现中通常都以的某个成员。

一般来说,在不同的实现中通常都以SxSx或或者者SySy的代表作为新集合的代表。

此后,由新的集合的代表作为新集合的代表。

此后,由新的集合SS代替了原来代替了原来的的SxSx和和SySy。

FIND-SETFIND-SET(xx)返回一个包含返回一个包含xx的集合的代表。

的集合的代表。

并查集的数组实现并查集的数组实现输入样例:

输入样例:

10710724245757131389891212565623233334347107108989UNIONUNION(x,yx,y)过程演示:

)过程演示:

12345678910SS123456789101234567891011115558810SS1234567891012345678910用数组用数组sisi记录元素记录元素ii所属集合的编号。

所属集合的编号。

MAKE-SETMAKE-SET(xx):

初始化只要):

初始化只要sisi:

=i=i;FIND-SETFIND-SET(xx):

):

查找元素所属的集合时,只需读出查找元素所属的集合时,只需读出sisi,时间,时间复杂度为复杂度为O

(1)O

(1)。

UNIONUNION(x,yx,y):

):

合并两元素各自所属的集合时,需要将数组中属合并两元素各自所属的集合时,需要将数组中属于其中一个集合的元素所对应的数组元素值全部改为另一个集合于其中一个集合的元素所对应的数组元素值全部改为另一个集合的编号值,时间复杂度为的编号值,时间复杂度为O(nO(n)。

实现简单,实际使用较多。

但是合并的代价太大,在最坏情实现简单,实际使用较多。

但是合并的代价太大,在最坏情况下,所有集合合并成一个集合的总代价会达到况下,所有集合合并成一个集合的总代价会达到O(nO(n22)。

每每个个集集合合对对应应一一个个链链表表,它它有有一一个个表表头头,每每一一个个元元素素有有一一个个指指针针指指向向表表头头,表表明明了了它它所所属属的的类类,另另有有一一个个指指针针指指向向它它的的下下一一个个元元素素,同同时时为为了了方方便便实实现现,再再设设一一个个指指针针lastlast表表示示链链表表中中的最后一个元素(表尾)。

的最后一个元素(表尾)。

当当然然,由由于于处处理理的的对对象象一一般般都都是是连连续续整整数数,所所以以,可可以以选选择静态数组(通过下标)来模拟实现,如:

择静态数组(通过下标)来模拟实现,如:

typetypenode=recordnode=recordhead,next,last:

integerhead,next,last:

integer;end;end;varvarS:

array1.maxnofnode;S:

array1.maxnofnode;并并查集的集的链表表实现MAKE-MAKE-SET(xSET(x):

Sx.headSx.head=x;Sx.nextx;Sx.next=0;=0;FIND-FIND-SET(xSET(x):

returnreturnSx.headSx.head;两个过程的时间复杂度都为两个过程的时间复杂度都为O

(1)O

(1)。

采采用用链链表表时时,当当有有两两个个元元素素(x,yx,y),),若若FIND-SETFIND-SET(xx)FIND-SETFIND-SET(yy),则则两两者者对对应应不不同同的的集集合合,需需要要将将两两个个链链表表合合并并,做做法法是是将将一一个个表表的的表表头头直直接接接接到到另另一一个个表表的的表表尾尾,这这一一步步操操作作看看似似很很简简单单,但但势势必必造造成成修修改改后后需需要要把把接接上上去去的的那那个个表表的的所所有有headhead值值修修改改,这这需需要要线线性性的的赋赋值值操操作作,其其复复杂杂度度与与选选择择接接在在尾尾部的链表长度成正比。

部的链表长度成正比。

UNION(x,yUNION(x,y):

假设假设UNION(x,yUNION(x,y)的参数是有序的,即把的参数是有序的,即把yy属于的集合合并到属于的集合合并到xx的集合有两种实现方法:

的集合有两种实现方法:

(11)简单实现)简单实现不考虑任何因素,出现不考虑任何因素,出现FIND-SETFIND-SET(xx)FIND-SETFIND-SET(yy)时,直接将)时,直接将yy的表的表头接到头接到xx的表尾,同时将的表尾,同时将yy中所在集合元素的中所在集合元素的headhead值设为值设为FIND-FIND-SET(xSET(x)。

同时。

同时xx的的表尾也应该设为原表尾也应该设为原yy表的表尾。

表的表尾。

注意:

注意:

lastlast指针其实只要在表头结点中记录即可,因为每一次查到指针其实只要在表头结点中记录即可,因为每一次查到FIND-FIND-SETSET(xx)都可以得到表头元素。

而链表中其他元素重新记录)都可以得到表头元素。

而链表中其他元素重新记录lastlast是无意义的。

是无意义的。

我们总是把我们总是把yy接到接到xx里去,那么如果里去,那么如果yy所在的集合非常大,每次赋值的代价就所在的集合非常大,每次赋值的代价就会非常高,考虑输入数据的特殊性,比如出现输入为:

会非常高,考虑输入数据的特殊性,比如出现输入为:

(22,11),(),(33,11),(),(44,11),(),(55,11),(),(66,11),(n,1)(n,1)最坏情况下时间复杂度为最坏情况下时间复杂度为O(n2)O(n2)。

(22)快速实现)快速实现上述简单实现非常不理想,针对上述简单实现非常不理想,针对yy可能比较大的这个问题,可可能比较大的这个问题,可以很快产生一个聪明的想法:

不妨比较以很快产生一个聪明的想法:

不妨比较xx和和yy所在集合的大小,从所在集合的大小,从而作出选择,把较短的链表接在较长的尾部,这样效果是一样的,而作出选择,把较短的链表接在较长的尾部,这样效果是一样的,但耗费肯定不比原来差。

这就是快速实现的思路。

可以在但耗费肯定不比原来差。

这就是快速实现的思路。

可以在nodenode里里多设一个域多设一个域numbernumber,用来记录此条链表中成员的个数。

显然,用来记录此条链表中成员的个数。

显然numbernumber记录在表头元素中即可,将两表合并的时候,只要将表的记录在表头元素中即可,将两表合并的时候,只要将表的numbernumber相加,因此维护起来是非常方便的。

相加,因此维护起来是非常方便的。

这种快速实现的方法可以称为这种快速实现的方法可以称为加权启发式合并加权启发式合并,这里的权就,这里的权就是指所记录的是指所记录的numbernumber。

可以证明这种方法的效率。

当有可以证明这种方法的效率。

当有nn个元素时,在个元素时,在UNIONUNION上的上的花费(即重新赋值的次数)的上界是花费(即重新赋值的次数)的上界是O(nlogO(nlog22n)n)。

因为:

考虑一。

因为:

考虑一个固定的对象个固定的对象xx,当,当xx的代表指针(的代表指针(headhead)被更新时,)被更新时,xx必是属必是属于一个较小的集合,因此,于一个较小的集合,因此,xx的代表指针第一次更新后,结果的代表指针第一次更新后,结果集合必然至少有集合必然至少有22个元素,类似的,下一次更新后,个元素,类似的,下一次更新后,xx所在的集所在的集合至少有合至少有44个元素。

继续下去,可以发现,个元素。

继续下去,可以发现,xx的代表指针最多被的代表指针最多被更新更新loglog22nn次,因为当次,因为当xx所在集合元素已经等于所在集合元素已经等于nn以后,不可能再以后,不可能再发生发生UNIONUNION操作。

所以,总共有操作。

所以,总共有nn个元素时,操作的总次数不超个元素时,操作的总次数不超过过nlognlog22nn次。

这就保证了整个算法的复杂度是理想的。

次。

这就保证了整个算法的复杂度是理想的。

并查集的链表实现是一种非常容易接受的算法,并且它并查集的链表实现是一种非常容易接受的算法,并且它的效率也是令人满意的。

其实它的思路和数组完全一样,所的效率也是令人满意的。

其实它的思路和数组完全一样,所以实际使用较少。

以实际使用较少。

合并两个集合时的实现过程如下:

合并两个集合时的实现过程如下:

UNION(x,yUNION(x,y)x=FIND-x=FIND-SET(xSET(x););y=FIND-y=FIND-SET(ySET(y););ififx.numberx.numbery.numbery.numberthenthenUNION(x,yUNION(x,y)elseelseUNION(y,xUNION(y,x););我们用有根树来表示集合,树中的每个节点包含集合的一个我们用有根树来表示集合,树中的每个节点包含集合的一个成员,每棵树表示一个集合。

多个集合形成森林态,以每棵树的成员,每棵树表示一个集合。

多个集合形成森林态,以每棵树的树根作为集合的代表,并且根结点的父结点指向其自身,树上的树根作为集合的代表,并且根结点的父结点指向其自身,树上的其他结点都用一个父指针表示它的附属关系。

其他结点都用一个父指针表示它的附属关系。

注意:

在同一棵树中的结点属于同一个集合,虽然它们在树注意:

在同一棵树中的结点属于同一个集合,虽然它们在树中存在父子结点关系,但并不意味着它们之间存在从属关系。

树中存在父子结点关系,但并不意味着它们之间存在从属关系。

树的指针起的只是联系集合中元素的作用。

的指针起的只是联系集合中元素的作用。

在并查集中,每个分离集合对应的一棵树,称为分离集合树。

在并查集中,每个分离集合对应的一棵树,称为分离集合树。

整个并查集也就是一棵分离集合森林。

整个并查集也就是一棵分离集合森林。

并并查集的集的树实现如如如如下下下下图图图图表表表表示示示示了了了了这这这这种种种种关关关关系系系系,其其其其包包包包含含含含两两两两个个个个集集集集合合合合b,c,e,h,d,f,gb,c,e,h,d,f,gb,c,e,h,d,f,gb,c,e,h,d,f,g分别以分别以分别以分别以cccc和和和和ffff作为代表。

作为代表。

作为代表。

作为代表。

这这这这种种种种树树树树结结结结构构构构,也也也也可可可可以以以以简简简简单单单单地地地地用用用用静静静静态态态态数数数数组组组组实实实实现现现现,设设设设pxpxpxpx表示表示表示表示xxxx元素所指向的父亲。

元素所指向的父亲。

元素所指向的父亲。

元素所指向的父亲。

MAKE-MAKE-MAKE-MAKE-SET(xSET(xSET(xSET(x):

pxpxpxpx=x;=x;=x;=x;FIND-FIND-FIND-FIND-SET(xSET(xSET(xSET(x):

要要要要从从从从xxxx开开开开始始始始,向向向向上上上上寻寻寻寻找找找找它它它它的的的的父父父父亲亲亲亲,直到找到根为止。

直到找到根为止。

直到找到根为止。

直到找到根为止。

UNIONUNIONUNIONUNION(x,yx,yx,yx,y):

只只只只要要要要使使使使一一一一棵棵棵棵树树树树的的的的根根根根指指指指向向向向另另另另一一一一棵棵棵棵树树树树的根,即成为一棵子树。

的根,即成为一棵子树。

的根,即成为一棵子树。

的根,即成为一棵子树。

1111查找一个元素所属的集合查找一个元素所属的集合查找一个元素所属的集合查找一个元素所属的集合在在在在分分分分离离离离集集集集合合合合森森森森林林林林中中中中,每每每每一一一一棵棵棵棵分分分分离离离离集集集集合合合合树树树树对对对对应应应应一一一一个个个个集集集集合合合合。

要要要要查查查查找找找找某某某某一一一一元元元元素素素素所所所所属属属属的的的的集集集集合合合合,就就就就是要找这个元素对应的结点所在的分离集合树。

是要找这个元素对应的结点所在的分离集合树。

是要找这个元素对应的结点所在的分离集合树。

是要找这个元素对应的结点所在的分离集合树。

查查找找树树的的根根结结点点的的方方法法很很简简单单,只只需需任任取取树树中中一一结结点点(不不妨妨就就取取我我们们要要查查找找的的那那个个结结点点),沿沿父父结结点点方方向向一一直直往往树树根根走走:

初初始始时时,取取一一个个结结点点,走走到到它它的的父父结结点点,然然后后以以父父结结点点为为基基点点,走走到到父父结结点点的的父父结结点点直直至至走走到到一一个个没没有有父父结结点点的的结结点点为为止止,这这个个结结点点就就是是树树的的根根结结点点。

如如图图,描描述述了了查查找找一一个个结结点点的的过过程程(黑黑色色结点为当前查找结点)。

结点为当前查找结点)。

2222两个元素各自所属的集合的合并两个元素各自所属的集合的合并两个元素各自所属的集合的合并两个元素各自所属的集合的合并在在在在分分分分离离离离集集集集合合合合森森森森林林林林中中中中,分分分分离离离离集集集集合合合合是是是是用用用用分分分分离离离离集集集集合合合合树树树树来来来来表表表表示示示示的的的的。

要要要要合合合合并并并并两两两两个个个个元元元元素素素素各各各各自自自自所所所所属属属属的的的的集集集集合合合合,也也也也就就就就是是是是合合合合并并并并两两两两元元元元素素素素所所所所对对对对应应应应的的的的两两两两个个个个结结结结点点点点各各各各自自自自所在的分离集合树。

所在的分离集合树。

所在的分离集合树。

所在的分离集合树。

考考虑虑到到在在分分离离集集合合森森林林中中,只只要要结结点点属属于于同同一一棵棵树树,即即被被视视为为在在同同一一个个集集合合中中,而而不不管管具具体体是是如如何何相相连连的的。

那那么么,我我们们只只需需简简单单的的将将一一棵棵分分离离集集合合树树作作为为另另一一棵棵的的子子树树,即即可可使使两两棵棵树树合合并并为为一一棵棵。

如如图图,描描述述的的是是将将两两棵棵分分离离集集合合树树D1D1和和D2D2合合并并的的过过程程(D1D1作作为为D2D2的的根根结结点点的一棵子树)。

的一棵子树)。

33优化查找与合并算法优化查找与合并算法优化合并过程优化合并过程如如果果两两棵棵分分离离集集合合树树AA和和BB,深深度度分分别别为为hAhA和和hBhB,则若,则若hAhAhBhB,应将,应将BB树作为树作为AA树的子树的子树;否则,将树;否则,将AA树树作为作为BB树的子树。

树的子树。

优化查找过程优化查找过程对对于于查查找找过过程程有有两两个个方方面面的的启启发发式式方方法法都都很很有效,分别是按秩合并和路径压缩优化。

有效,分别是按秩合并和路径压缩优化。

AA按秩合并按秩合并进进行行UNIONUNION的的时时候候,只只要要让让具具有有较较小小秩秩的的根根指指向向具具有有较较大大秩秩的的根根。

如如果果两两根根的的秩秩相相等等,只只要要使使其其中中一一个个根根指指向向另另一一个个,同同时时秩秩应应当当增增加加11。

这这十十分分类类似似于于统统计计节节点点个个数数,但但这这里里统统计计的的是是树树的的深深度。

度。

BB路径压缩优化方法路径压缩优化方法在在查查找找一一个个结结点点所所在在树树的的根根结结点点的的过过程程中中,要要经经过过一一条条从从待待查查结结点点到到根根结结点点的的路路径径。

我我们们不不妨妨就就让让这这些些路路径径上上的的结结点点直直接接指指向向根根结结点点,作作为为根根结结点点的的子子结结点点。

这这样样,这这些些路路径径上上的的结结点点仍仍在在分分离离集集合合中中,整整棵棵树树仍仍然然满满足足分分离离集集合合树树的的要要求求,而而路路径径上上的的结结点点的的深深度度无无疑疑降降低低了了,这这些些点点及及其其子子树树上上的的结结点点的的查查找找复复杂杂度度大大大大降降低。

低。

如如如如图图图图,描描描描述述述述了了了了在在在在一一一一棵棵棵棵分分分分离离离离集集集集

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1