一、定义
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。
二、代码实现
在并查集结构中,用一个pre[]
数组来存储当前结点的父亲结点,有两个函数,found()
函数用来寻找根结点,join()
函数用来合并两个并查集。
初始化
把每个结点的父亲结点初始化为自己
1 void init() 2 { 3 for(int i=0;i<n;i++) 4 pre[i]=i; 5 }
found()
函数
寻找当前结点的根结点
1 int found(int x) 2 { 3 int r=x; 4 while(r!=pre[r]) 5 { 6 r=pre[r]; 7 } 8 int i=x,j; 9 while(i!=r)//路径压缩 10 { 11 j=pre[i]; 12 pre[i]=r; 13 i=j; 14 } 15 return r; 16 }
路径压缩是防止并查集查询的时间复杂度退化为O(n),形成一条链,因此把路径上的父亲结点全部设为根结点
同时路径压缩也可以通过递归来实现
1 int found(int x) 2 { 3 return pre[x]=(x==pre[x]?x:found(pre[x])); 4 }
join()
函数
用来合并两个并查集,先判定两个结点是否属于一个并查集,如果不属于,则将x根结点的父亲结点设为y的根结点
1 void join(int x,int y) 2 { 3 int a=find(x); 4 int b=find(y); 5 if(a!=b) 6 { 7 pre[a]=b; 8 } 9 }
除了使用路径压缩来防止并查集退化外,还可以使用启发式优化,在每次合并时将层数少的树合并到层数多的树上。