您的位置:首页 > 其它

并查集 入门 以及状态压缩 C

2016-07-27 20:07 330 查看
并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题。一些常见的用途有求连通子图、求最小生成树的
Kruskal 算法和求最近公共祖先(Least Common Ancestors, LCA)等。

使用并查集时,首先会存在一组不相交的动态集合 S={S1,S2,⋯,Sk}S={S1,S2,⋯,Sk},一般都会使用一个整数表示集合中的一个元素。、

顾名思义 并查集有两个操作:

1:合并两个集合

2:查找某元素属于哪个集合

并查集的实现原理也比较简单,就是使用树来表示集合,树的每个节点就表示集合中的一个元素,树根对应的元素就是该集合的代表 如图

           

   


                        并查集的表示                           初始化并查集
 有{a,b,d,c}和{e,f,g}两个集合其中a,和e分别为l两棵数的根也是各个集合的代表,对于并查集这种数据结构查找一个元素是否在集合里面相对是比较快的它仅仅只需要不断寻找其父节点一直到根节点复杂度为O(N)并且其实现方法也相对容易,只需用一个一维数组来保存其父指针(开始起指针指向他自己即A
=N)同样合并两个集合只需要将其中一个集合的根指针指向另一集合的根即可
查找代码:
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
}
合并代码:
merge2(a, b)
{
if (a<b)
set[b] = a;
else
set[a] = b;
}




但是当一个集合形成的树深度太深在递归的时候便失去啦它的意思还用可能当树退化成一根链事其处理和数组就差不多啦,对于这种问题通常有两种解决方法
1:将深度小的集合合并在深度大的集合上去;
2:路径压缩;
路径压缩:路径压缩,就是在每次查找时,令查找路径上的每个节点都直接指向根节点如图



同样路径压缩有两个方法分别为递归版和非递归版
递归版:
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;         //返回根节点的值            
}
图片等资料来自于:作者:CYJB 
出处:http://www.cnblogs.com/cyjb/ 
GitHub:https://github.com/CYJB/ 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: