您的位置:首页 > 其它

并查集及其链表与不相交集合森林实现

2010-10-13 21:06 288 查看
在需要判断两个对象是否属于同一集合的应用时,并查集是一种非常有效的数据结构。并查集具有MAKE-SET,FIND-SET,UNION三个基本操作。定义一个具有m个MAKE-SET,FIND-SET,UNION(其中n个MAKE-SET操作)的操作序列。这个操作序列中UNION的操作次数不多于n-1(因为每次UNION都会使集合数减少1)。

采用链表是实现并查集的一种非常便捷的方式。每个集合有一个头指针和尾指针。每个对象均有一个指针域的指针指向代表元素,代表元素可以任意选择,若要集合具有一定的性质也可以对集合中的元素按照一定的规则排列(如排序等)。



若采用链表的方式实现,MAKE-SET操作的时间为O(1),FIND-SET操作的时间为O(1),两个集合合并,利用尾指针就可以快速定位需要链接的地方。其中改变头指针和尾指针只需要常数时间,而每次UNION的时间为O(n),最多n-1次UNION操作,故总时间为O(n^2)。

若UNION时采用带权合并,即将长的集合合并到短的集合后,那么总的UNION的时间为O(nlgn),因为每个对象第一次改变代表元素指针后其集合长度不小于2,第二次改变代表元素指针后其集合长度不小于2^2,第lgn次改变代表元素指针后其集合长度不小于n,而集合的最大长度为n,故最多改变代表元素指针的次数为lgn。共有n个对象,故UNION操作的时间为O(nlgn)。

采用不相交集合森林实现并查集是渐进效率最高的一种方式。m个MAKE-SET,FIND-SET,UNION(其中n个MAKE-SET操作)的操作序列需要的时间为(n*alpha(n)),其中alpha(n)<=4.不想交集合森林采用两种启发式的算法:



1)按秩合并。其中秩定义为从根到叶子的最大高度,将秩小的集合合并到秩较大的集合上。

2)路径压缩。FIND-SET操作是一个两趟方法,第一遍从下往上找到根节点,第二遍从上往下将查找路径上的每个对象的代表对象指针均指向根结点。

不相交集合森林实现并查集的伪代码如下:

MAKE-SET(x)
1 p(x)<-x
2 rank[x]<-0

UNION(x,y)
1 LINK(FIND-SET(x),FIND-SET(y))

LINK(x,y)
1 if rank[x]>rank[y]
2    then p[y]<-x
3         if rank[x]=rank[y]
4            then rank[y]<-rank[y]+1

FIND-SET(x)
1 if x!=p[x]
2    then p[x]<-FIND-SET(p[x])
3  return x
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: