码迷,mamicode.com
首页 > 其他好文 > 详细

计算机算法学习(1) - 不相交集合数据结构

时间:2014-08-04 06:13:46      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:blog   http   使用   io   数据   for   2014   问题   

不相交集合 故名思意就是一种含有多个不相交集合的数据结构。典型的应用是确定无向图中连通子图的个数。其基本操作包括:

Make-Set(x):建立一个新的集合,集合的成员是x;

Union(x,y): 将包含x和y的集合合并为一个集合;

Find-Set(x): 返回指向包含x的集合的指针;

下面是一个例子,(a)是一个无向图,(b)是使用不相交集合来找连通子图的个数。做法是初始为各个顶点为一个集合,然后遍历各个边,把边的端点的集合进行合并,当处理完所有的边,能连通的顶点就在一个集合里了,这样就生成了4个集合。也就是有4个连通子图。

bubuko.com,布布扣

如何实现不相交集合呢?

最直观和简单的方法是用链表:每个集合是一个链表,合并时,就是把一个链表接到另一个链表的后面。由于需要支持Find-Set操作,所以,每个元素都需要有指针指向集合的头节点。更新链表也需要更新这个头指针,使其指向新集合的头。如果我们不考虑合并时两个集合的大小,那最坏情况下是把长的接到短的后面,这样就需要更新更多的头指针。而简单的优化方式就是总是把短的链表接到长的后面。

更好的方式是用有根树来表示。如果不做优化,有根树并不比链表快很多,但是使用按秩合并和路径压缩两种优化后,可以得到跟操作数量m成线性关系的运行时间。

按秩合并:基本思想是跟链表时的优化类似,当两个集合(树)要合并时,将小的集合并到大的里面。所采取的方法并不是记录集合的大小,而是用秩来描述,秩是集合树高度的一个上界。在Union时,两个要合并的集合x,y。如果x的秩大,那就把y并入x:将y的根的父节点设置为x的根,这时x的秩是不需要改变的,因为高度没有改变,只是增加了x的根的子节点的数量,但如何x和y的秩相同,那就随机把某个根的父节点设置为另一个的根,但这时需要把秩增加1.

路径压缩:路径压缩是说在Find-Set时,将查找路径上的每个节点都直接指向其根节点,也就是把树的高度变小了,根节点的孩子多了。但这些操作并不改变秩的大小。所以这里的秩只是一个模糊的上界,并不真的表示树的高度。 路径压缩的好处就是,在后续的Find-Set操作可以变快,下图中Find-Set(a)时把搜索路径上所有的节点的父节点都成了根节点,那后续的Find-Set(b)就可以一步完成了。

bubuko.com,布布扣

不相交集合的使用还是可以比较灵活的,遇到有环的问题,也许可以考虑,下面是勇幸|Thinking分享的一个题目:

A zero-indexed array A consisting of N different integers is given. The array contains all integers in the range [0..N−1]. Sets S[K] for 0 ≤ K < N are defined as follows: S[K] = { A[K], A[A[K]], A[A[A[K]]], ... }. Sets S[K] are finite for each K.

Write a function:

class Solution { public int solution(int[] A); }

that, given an array A consisting of N integers, returns the size of the largest set S[K] for this array. The function should return 0 if the array is empty.

这个问题也是比较适合用这个不相交集合这种数据结构来解决的。

 

计算机算法学习(1) - 不相交集合数据结构,布布扣,bubuko.com

计算机算法学习(1) - 不相交集合数据结构

标签:blog   http   使用   io   数据   for   2014   问题   

原文地址:http://www.cnblogs.com/whyandinside/p/3889234.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!