并查集的优化:按秩合并和路径压缩

来源:互联网 发布:亚马逊 云计算 发展史 编辑:程序博客网 时间:2024/06/08 10:25

转载于:http://www.tuicool.com/articles/Zb2qYzj

并查集有两个优化。

一、按秩合并

描述:就是在对两个不同子集连接时,按照rank来连,也就是rank低的连在rank高的下面。rank高的做父亲节点。

作用,这样类似维护了一棵树,树是rank高的在上。

// 初始化n个元素void init(int n){    for(int i=0;i<n;i++)    {        parent[i]=i;        rank[i]=0;   // 初始树的高度为0    }}// 合并x和y所属的集合void unite(int x,int y){    x=find(x);    y=find(y);    if(x==y) return ;    if(rank[x]<rank[y])        parent[x]=y;  // 合并是从rank小的向rank大的连边    else    {        parent[y]=x;        if(rank[x]==rank[y]) rank[x]++;    }}

二、路径压缩

描述:假如fa数组已经嵌套了N层,那么传统的做法去找祖先要做N次,当N很大时,这种做法很没效率。

这是朴素查找的代码,适合数据量不大的情况

int findx(int x){    int r=x;   while(parent[r] !=r)        r=parent[r];   return r;}

    下面是采用递归路径压缩的方法查找元素,但是,递归压缩路径可能会造成溢出栈会发生RE

int find(int x)       //查找x元素所在的集合,回溯时压缩路径{    if (x != parent[x])    {        parent[x] = find(parent[x]);     //回溯时的压缩路径    }         //从x结点搜索到祖先结点所经过的结点都指向该祖先结点    return parent[x];}

下面我们说一下非递归方式进行的路径压缩

int find(int x){    int k, j, r;    r = x;    while(r != parent[r])     //查找跟节点        r = parent[r];      //找到跟节点,用r记录下    k = x;            while(k != r)             //非递归路径压缩操作    {        j = parent[k];         //用j暂存parent[k]的父节点        parent[k] = r;        //parent[x]指向跟节点        k = j;                    //k移到父节点    }    return r;         //返回根节点的值            }
0 0
原创粉丝点击