并查集(Union Find)的实现及代码应用

前言

  之前我们在连通分量的个数那个题中提到了并查集,可是我们还是没有正式讲解并查集的使用方法,下面我们来正式讲一下并查集的使用及实现

  我们要知道,并查集包含两部分,并(union)和查(find),他们是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,

  其间可以查找一个元素在哪个集合中,也可以查找一共有几个集合。

  并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

1.find函数

  find函数是用来查找各个点的上级的,作为上级的结点的上级为其本身,如1->2->3此三个点为同一类,那么将1的pre数组设为其本身,将2和3的pre数组按递归的方式变为pre[ 1 ],以此类推。

  代码实现如下:

int pre[1000 ];

int find(int x)  //查找根节点
{ 
    int r=x;
    while ( pre[r] != r ) //返回根节点 r    
       {
            r=pre[r];
       }
    int i=x , j ;
    while( i != r )  //路径压缩
    {
         j = pre[i]; // 在改变上级之前用临时变量  j 记录下他的值 
         pre[i]= r ; //把上级改为根节点
         i=j;
    }
    return r ;
}                        

2.Union函数

  union函数就是将不连通的分量连通起来,归为同一个类

  代码实现如下:

/*判断x y是否连通,如果已经连通,就不用管了;如果不连通,就把它们所在的连通分支合并起来*/
void union(int x,int y)                                                                                                    
{
    int fx=find(x),fy=find(y);
    if(fx!=fy) 
    {
         pre[fx ]=fy;
    }
}    

3.时间复杂度分析

  空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M查找的时间复杂度为O(Mα(N)),这里α是Ackerman函数的某个反函数。

4.应用

  并查集常作为另一种复杂的数据结构或者算法的存储结构。常见的应用有:

  •  求无向图的连通分量个数
  •  最近公共祖先(LCA)
  •  带限制的作业排序
  •     实现Kruskar算法求最小生成树

5.参考资料

  https://blog.csdn.net/u013546077/article/details/64509038

  https://blog.csdn.net/chen_lin111/article/details/50408379

原文地址:https://www.cnblogs.com/syycjh/p/9516267.html