并查集:按秩归并&路径压缩

匿名 (未验证) 提交于 2019-12-03 00:30:01

集合可以怎么表示?可以用一棵树来表示,结点表示集合的元素,而树根则用来代表这个集合。所以用树来做集合的并查集的话,对于查找某个元素属于哪个集合,我们就从这个结点开始往上找,找到它所在的这棵树的根结点。对于并集操作,只要把两棵树的根结点并在一起就可以了。所以为了满足这样的操作,我们的树结构有点小改变,变为双亲表示法“由孩子指向双亲。每个结点都向上指向它的父结点,而不是由父结点向下指向左右子树。”这样的树比较好的是用结构体数组来存储表示。

集合建立好后,接下来看查找操作:

38forXi=0iMaxSizeS[ i ].Data!=Xi++iXXS[ i ].Parent>=0S[ i ].ParentiS[ i ].Parent<0return i

接着到集合的并运算。并运算是指给出两个元素的值,让你把这两个元素所在的集合并合在一起。这样操作我们要这样做:

1、首先要找到这两个元素所在的树的根结点(也就是找到这两个集合)。

2、判断这两个元素所在的集合是不是同一个集合,如果不是就做并运算,把其中一个树较矮的根结点指向另一个树较高的根结点的数组下标。


Parent

为什么要做这样一个查找操作?如果我们随便就把两棵树合并在一起,会出现怎样的一种情况?例如如果我们把一棵较高的树指向一棵较矮的树,那么合并后树的最大高度就会增加,随着并运算的操作次数越多,树变得越来越高,越往后那么集合的查找操作效率就会变得越来越低,因为查找操作是从要查找的结点元素开始一层一层往上找根结点,当集合树高度很大时,要遍历的层数就越多,效率就变得越低了。

所以为了解决这个问题,优化树变高后查找操作的效率,就要用到按秩归并。我们应该把较矮的树指向并到较高的树上(或者把规模小的树接到规模大的树上),这样较矮的树高度增加了,但较高的树高度没有增加,合并后的整棵树最大高度仍然是之前较高的树的高度,所以合并后树的最大高度并没有增加。


ParentParent62Parent

通过按秩归并对集合的并运算做优化后,程序运行就快了。其实我们可以继续做优化,用路径压缩。

首先我们看回上面的查找函数


39i0nnnn


Data0n-1ElementType Data


XS[ X ].Parent0CompressS[ X ].ParentXS[ X ].Parent<0return X

F110



Xreturn S[X].Parent=CompressFind(S, S[X].Parent);S[ X ].Parentrenturnreturn


F


这就是路径压缩,不仅在查找操作中找到了集合的根结点,同时把集合的路径压缩,这里的路径压缩指把每次扫过的结点都接上根结点上。这样做的好处在于,在做多次查找操作时,因为路径压缩了,所以会省去很多的时间。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!