前言
之前我们在连通分量的个数那个题中提到了并查集,可是我们还是没有正式讲解并查集的使用方法,下面我们来正式讲一下并查集的使用及实现
我们要知道,并查集包含两部分,并(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