并查集

并查集:(union-find sets)

一种简单的用途广泛的集合.并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数等。最完美的应用当属:实现Kruskar算法求最小生成树。

主要操作:

合并两个不相交集合操作很简单:先设置一个数组Father[x],表示x的“父亲”的编号。那么,合并两个不相交集合的方法就是,找到其中一个集合最父亲的父亲(也就是最久远的祖先),将另外一个集合的最久远的祖先的父亲指向它。

判断两个元素是否属于同一集合仍然使用上面的数组。则本操作即可转换为寻找两个元素的最久远祖先是否相同。可以采用递归实现。

并查集的优化

路径压缩

刚才我们说过,寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的。

对此,我们必须要进行路径压缩,即我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面。这就是路径压缩了。

Rank合并

C语言代码:合并时将元素所在深度低的集合合并到元素所在深度深的集合。<以上摘自网络>

#include <iostream>
using namespace std;
int f[n];   //  记录节点n的父节点
int find(int x)
{
   if(f[x]==x)  // 根节点的父节点是其本身,找到的时候就可以返回了
       return x;    //返回根节点           
   else
       f[x]=find(f[x]);  //运用回朔返回的根节点为f[x]重新赋值。
   return f[x];
}
int merger(int x,int y)  //合并操作
{
    f[x]=y;   //把集合x的父节点设置为y. 完成x集合与Y集合的合并。
              // PS:x是X集合的根节点,y是Y集合的根节点。合并不能随便选取节点,必须要根节点;   

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值