并查集

来源:互联网 发布:sftp 命令行 指定端口 编辑:程序博客网 时间:2024/06/08 02:40

并查集:

并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作。

主要组成部分及操作:

1,初始化:初始化后,每一个元素的父亲节点是他本身,每一个元素的祖先节点也是他本身

 C++ Code 
1
2
3
4
5
6
7
void makeSet(int n)
{
    for (int i = 0; i < n; i++)
    {
        par[i] = i;
    }
}

2,查找:查找一格元素所在的集合,也就是找到这个元素所在集合的祖先。(通常在查找的过程中加入路径压缩)

递归写法:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
/* 查找x元素所在的集合,回溯时压缩路径*/

int Find_Set(int x)
{
    if (x != father[x])
    {
        father[x] = Find_Set(father[x]); //这个回溯时的压缩路径是精华
    }
    return father[x];
}
非递归写法:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int Find(int x)  ///查找根节点
{
    int r = x;
    while(r != pre[r])  ///返回路径r
        r = pre[r];

    int i = x, temp;
    while(pre[i] != r)  ///压缩路径
    {
        temp = pre[i]; ///在改变上级之前用临时变量  j 记录下他的值
        pre[i] = r;   ///把上级改为根节点
        i = temp;
    }
    return r;
}
ps:建议用递归写法,代码简洁。

3,合并操作:合并两个不相交集合的操作,先利用查找操作找到两个集合的祖先,将一个集合的祖先指向另一个集合的祖先

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
void Union(int r1, int r2)
{
    ///并
    int t1 = fin_d(r1);
    int t2 = fin_d(r2);

    if(t1 != t2)
    {
        a[t2] = t1;         ///合并子节点
    }
}

总的来说,并查集由一个数组,一个查找操作以及一个合并操作组成,

有的题目在合并的时候 需要根据  秩 合并,并实时更新 秩 ,只不过是多加了一个数组存储 秩。