并查集

来源:互联网 发布:工程网络计划sts 编辑:程序博客网 时间:2024/05/29 06:33

我之前在无向图的连通性问题上使用到了并查集的方法。现在我系统整理一下。

并查集:

是什么:

它是一种用来管理元素分组情况的一个数据结构。


做什么:

  • 查询元素a和元素b是否在同一组。
  • 合并元素a和元素b所在的组。
    注意:并查集虽然可以进行合并操作,但是无法进行分割操作。

结构:

并查集是使用树形结构实现的,但是不是二叉树。
每个元素对应一个结点,每个组对应一棵树。


实现过程

  1. 初始化:
    用一个数组保存每个结点的父结点,最开始,每个结点的父结点都是自己,它们互相独立。没有边

    void Init(){    for(int i=0; i<n; i++)    {        par[i] = i;     }       return 0;}
  2. 合并:
    从一个组的根向另一个组的根连边,这样两棵树就变成一棵树,即将两个集合合并为一个集合。

    /*合并x和y所属的集合*/void unite(int x, int y){    if(find(x)==find(y)) return;    else{        par[find(x)] = find(y);    }}   
  3. 查询:
    查询两个结点是否为同一个组:只要找到这两个结点的父结点是不是一个“人”,就能够知道是否为同一个组了。

    /*查找根节点*/int find(int x){    int r = x;    while(r!=pre[r])    r = pre[r];    return r;}

路径压缩:

如果一个树是长长的一棵,那么从叶子开始找它的根结点,那么复杂度就显得十分高了。所以我们要采用一个技巧——路径压缩,就是一旦找到每一个结点的根结点,直接把这个结点和它变成“直属”关系,即直接连到根上,这样下次再次查询就不会自顶向上一个个找了。

int find(int x){    int r = x;    while(r!=pre[r])    r = pre[r];    int i = x;//路径压缩     int j;      while(i != r)    {        j = pre[i];        pre[i] = r;        i = j;    }    return r;}
0 0
原创粉丝点击