并查集可以在O(α(n))时间内进行以下两种操作:
1)查询元素a和元素b是否属于同一组;
2)合并元素a和元素b所在的组;
ps:这是“均摊复杂度”,且比O(log(n))还要快;
并查集是使用树形结构实现的,为了避免发生退化,采用以下两种优化操作:
1)对于每课树,记录这棵树的高度(rank),合并从rank小的向rank大的连边;
2)路径压缩,对于每个节点,一旦向上走到了一次根节点,就把这个点到父亲的边改为直接连向根,同时,不仅仅是所查询的节点,在查询过程中向上经过的所有的节点,都改为直接连到根上;
代码:
int par[max_n];//父亲
int rank[max_n];//树的高度
//初始化n个元素
void init(int n)
{
for(int i=0;i<n;i++)
{
par[i]=i;
rank[i]=0;
}
}
//查询树的根
int find(int x)
{
if(par[x]==x)
return x;
else
return par[x]=find(par[x]);
}
//合并x和y所属的集合
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return ;
if(rank[x]<ran[y])
par[x]=y;
else
{
par[y]=x;
if(rank[x]==rank[y])
rank[x]++;
}
}
//判断x和y是否属于同一个集合
bool same(int x,int y)
{
return find(x)==find(y);
}