并查集算法原理

并查集

1.概念

简而言之,合并集合与查找集合于一身的数据算法。

2.性质

并查集算法不支持分隔一个集合。

3. 算法

一个集合,使用某个元素x作为代表元,来代表这个元素集合,所有元素组成以代表元为根的树形结构,对每个元素y的父节点都可指向根节点,即parent[y] = x。

所以,判断两个元素是否属于统一集合,只需要看他们代表元是否相等即可。

4. 并查集操作

一个并查集有三个操作。

  1. 集合初始化

建立一个新的并查集,里面包括多个单个元素的单独集合,每个单集合包含以下三个东西。

  1. 集合元素
  2. 集合的层次,通常用rank表示
  3. 该集合类别

结构表示方法:

struct Node

{

    int data;

    int rank;

    int parent;

 }

数组表示方法:

int set[max];//集合index的类别,或者用parent表示
int rank[max];//集合index的层次,通常初始化为0
int data[max];//集合index的数据类型
 
//初始化集合
void Make_Set(int i)
{
    set[i]=i;//初始化的时候,一个集合的parent都是这个集合自己的标号。没有跟它同类的集合,那么这个集合的源头只能是自己了。
    rank[i]=0;
}

  1. 查找函数

即查找集合parent的方法,如果集合的parent等于集合的编号(即还没有被合并或者没有同类),那么自然返回自身编号。

如果不同(即经过合并操作后指针指向了源头(合并后选出的rank高的集合))那么就可以调用递归函数。

int get_parent(int x)
{
    if(node[x].parent==x)
        return x;
    return get_parent(node[x].parent);
}

但是,如果每次都沿着父节点不断向上查找,时间复杂度就是树的高度,为了更高效,引入路径压缩的概念。

即每次查找时,令查找路径上的每个节点都直接指向根节点。

  1. 合并集合函数 
void Union(int a,int b)
{
    a=get_parent(a);
    b=get_parent(b);
    if(node[a].rank>node[b].rank)
        node[b].parent=a;
    else
    {    
        node[a].parent=b;
        if(node[a].rank==node[b].rank)
            node[b].rank++;
    }
}

简而言之,就是将一个集合的树根指向另一个集合的根,

两种合并策略:

  1. 按秩合并

秩是指树高度的上界,即将较矮的树添加到较高的树根节点上。

  1. 按元素个数合并

节点少的树合并到节点多的树根节点。

参考:

https://segmentfault.com/a/1190000004023326

https://www.jianshu.com/p/8c74df1db116

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值