首页 > 代码库 > 并查集

并查集

-----------------siwuxie095

   

   

   

   

   

   

   

   

并查集基础

   

   

这里介绍并查集(Union Find),它是一种很不一样的树形结构

   

   

   

并查集的作用:可以非常高效地回答连接问题

   

「连接问题,即 Connection Problem」

   

   

   

首先简单的采用可视化的方式来看连接问题,如下:

   

技术分享

   

   

在上图中有若干个点,点与点之间有可能相连

   

   

有这么一个问题:某两个点是不是连接在一起

   

如果这两个点比较近,通过这张图就可以非常容易看出来,它们是否

连接在一起

   

如果这两个点比较远,比如:左上角的点和右下角的点,只是通过人

眼来看这张图,就很难非常快速地回答这个问题

   

   

那么在这种情况下,就需要使用计算机,可是计算机如何高效地回答

这个问题呢?并查集这种数据结构就提供了一个非常好的解决方案

   

   

   

可能有人会问,在这样一张图判断两个点是否连接在一起,意义何在?

   

事实上,这只是一个抽象的问题的模型表述。连接问题在实际应用中

有着非常重要的作用

   

   

   

   

   

   

   

连接问题

   

   

连接问题最主要的一个作用就是可以判断网络中节点间的连接状态

   

注意:这里的 网络 是一个非常抽象的概念,并不一定就具体的代表

计算机网络

   

   

   

如:一个大型的社交网络,也是网络,即 用户之间形成的网络

   

FaceBook 中,用户和用户之间形成了好友的关系。那么这个好友的关系,

就是一种连接的关系,FaceBook 有很多用户,他们之间通过这种好友关系

的连接,就形成了一个巨大的网络

   

那么在 FaceBook 中就能问这样一个问题:任意的两个人A 和 B,他们之间

是否能够通过好友直接互相认识?这就是一个典型的连接问题

   

   

   

当然,网络不仅仅包含用户之间形成的社交网络,一个巨大的数据库中

有很多的音乐、电影、书籍这些多媒体之间也可以形成网络

   

更不用提互联网的网页之间,本身形成的也是网络,路由器和路由器之间

的数据交换形成的也是网络,另外还有 道路交通、航班调度这些全部

可以形成网络

   

那么在这些网络中,都可以使用并查集来回答类似的连接问题

   

   

   

   

   

   

   

集合

   

   

并查集还有另外一个非常重要的作用,就是可以实现数学中的集合

   

「数学中的集合类实现」

   

通过并查集的名字,大概也能看出来,并查集的,其实就是实现

一个并集的意思

   

所以,在使用数学中集合的思路解决问题时,如果经常使用并集操

作,同时需要查询元素在集合中的状态的话,并查集也是一个非常

好的选择

   

   

   

   

   

   

   

路径问题

   

   

可能有人看到了连接问题,就会想到一个相应的问题,叫做 路径问题

   

   

熟悉算法的人都会知道,经常会有这样的问题:这些节点之间既然已经

能够连接了,那么能不能从一个节点通过一条路径到达另外一个节点?

   

路径问题,在图论中会有所涉及

   

   

   

   

   

   

   

连接问题与路径问题

   

   

连接问题和路径问题的区别:连接问题 路径问题 回答的问题要少

   

   

不难想象,路径问题直接求出了两个节点之间连接的路径,具体是什

么,而连接问题只需要回答两个节点之间是否相连就够了

   

   

正因为连接问题回答的问题比路径问题少,所以能设计出更快的算法

来解决连接问题,而不求出两个节点之间具体的路径

   

   

   

   

   

事实上,在计算机算法领域,经常会遇到类似的问题,即 并不需要回答

那么多问题,也正因为如此,可以设计出更高效的算法

   

如下:

   

1)和 二分查找 作比较

   

现在要在一个有序数组中查找一个元素,可以使用二分查找法,也可以

使用顺序查找法

   

其中,二分查找法是 O(lgn) 的复杂度,顺序查找法是 O(n) 的复杂度

   

为什么顺序查找法会更慢一些呢?

   

一个更重要的原因就是:顺序查找法不仅查找到了这个元素,顺序查找

法还找到了这个元素在整个数组中的排名。也就是说,顺序查找法顺便

回答了 rank 这个问题

   

不仅如此,顺序查找法还把查找到的这个元素之前的所有元素的排名,

全部顺道求了出来,只不过我们不关心,所以没有存储,但是这个过

程都遍历了一遍。所以,二分查找法更高效

   

   

   

2)和 select 作比较

   

现在要在任意一个数组中找出排名第 n 的元素,可以使用快速排序的

partition 的思路,设计出一个 select 算法。不过对于这种问题,一

个更直观的想法是:可以直接把这个无序数组排一遍序,当排好序之

后,就能直接找到排名为 n 的元素

 

其中,使用快排的思路实现的 select,是 O(n) 级别的复杂度,而先

排序再求出排名第 n 的元素,是 O(n*lgn) 的复杂度

   

为什么排一遍序会更慢一些呢?

   

一个更重要的原因,就是排好序以后,不仅能够回答排名第 n 的元素

是多少,还能回答排名是 n-1 的元素是多少,n-2 的元素是多少 …

   

事实上,可以回答排名第 x 的元素是多少(0 <= x <= n)

   

也就是说,排好序之后,能够回答的问题更多。而使用快排的思路实

现的 select,能够回答的问题相对少一些,也正因为如此,这个算法

更高效

   

   

   

3)和 作比较

   

用堆这种数据结构,可以非常快速的找出数据中的最大值和最小值

   

堆这种数据结构之所以高效,也是因为在问题模型中,我们只关心

最大值 最小值,不关心第二名、第三名

   

正是应用了这样的性质,设计出了堆这种高效的数据结构

   

   

   

   

 

所以,当针对一个某问题设计出一个算法后,不妨问问自己,我们

所实现的这个算法除了回答了问题本身之外,是不是额外回答了一

些别的问题

   

如果我们的算法额外回答了一些别的问题,那么很有可能存在一个

更高效的算法。它之所以高效,正是因为它没有回答额外问题

   

   

   

   

   

   

   

   

   

【made by siwuxie095】

并查集