作用:
用于快速合并两个集合,判断两个元素是否属于同一集合,时间复杂度均为为O(logn)。
核心思路:
使用数组下标 i 存储元素 i 所属的集合。
功能:
查找find:找到节点的根,路径压缩,并在递归返回过程中,把路径上所有节点直接指向根。
合并merge:按秩合并,通过将较矮的树合并到较高的树下,避免合并后树高度不合理增长。
实现:
#include<bits/stdc++.h>
using namespace std;
const int MX = 200001;
int f[MX],trees[MX]; // f存储第i位的祖宗,原先f[i]=i
// 找祖宗
int find(int k){
return f[k]==k ? k : f[k] = find(f[k]); // 返回赋值语句
}
// 合并
void merge(int x,int y){
x = find(f[x]);
y = find(f[y]);
// 这里只是把祖宗换了,路过的其他数祖宗还是原来的,不过下次查询,合并时就会换
if (x==y) return;
// 合到x上
if (trees[x]<trees[y]) swap(x,y);
f[y] = x;
trees[x] += trees[y];
}
int main(){
// 初始化
memset(trees,1,sizeof(trees));
for (int i=0;i<MX;i++) f[i] = i;
// 合并点1,点2
merge(1,2);
// 判断点1,点2是否为同一集合
if (find(1)==find(2)){
cout<<"yes,is the same collection。"
}else{
cout<<"no,isn't the same collection。"
}
}