并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题。
用集合中的某个元素来代表这个集合,该元素称为集合的
一个集合内的所有元素组织成以代表元为根的树形结构。
对于每一个元素 parent[x]指向x在树形结构上的父亲节点。如果x是根节点,则令parent[x] = x。
对于查找操作,假设需要确定x所在的的集合,也就是确定集合的代表元。可以沿着parent[x]不断在树形结构中向上移动,直到到达根节点。
代表元
。一个集合内的所有元素组织成以代表元为根的树形结构。
对于每一个元素 parent[x]指向x在树形结构上的父亲节点。如果x是根节点,则令parent[x] = x。
对于查找操作,假设需要确定x所在的的集合,也就是确定集合的代表元。可以沿着parent[x]不断在树形结构中向上移动,直到到达根节点。
判断两个元素是否属于同一集合,只需要看他们的代表元是否相同即可。
为了加快查找速度,查找时将x到根节点路径上的所有点的parent设为根节点,该优化方法称为压缩路径。
使用该优化后,平均复杂度可视为Ackerman函数的反函数,实际应用中可粗略认为其是一个常数。
使用该优化后,平均复杂度可视为Ackerman函数的反函数,实际应用中可粗略认为其是一个常数。
并查集的主要操作有:
1-合并两个不相交集合
2-判断两个元素是否属于同一个集合
3-路径压缩
并查集的两种优化方法:路径压缩与按秩合并。
int pre[100],rank[100];//pre为其父节点,rank是当前元素所在集合的大小
//初始化
int init()
{
for(int i=0;i<100;i++)
{
pre[i]=i;
rank[i]=1;
}
}
//带路径压缩的非递归找根结点
int Find(int x)
{
int r=x;
//循环找到根节点
while(r!=pre[r])
r=pre[r];
int i=x,j;
//把每一个节点的pre设置为根节点
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
//带路径压缩的递归找根节点
int Find(int x)
{
if(pre[x]!=x)
pre[x]=Find(pre[x]);
return pre[x];
}
//按秩合并,元素少的集合的根节点指向元素多的集合的根节点
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x==y)
return;
if(rank[x]>=rank[y])
{
pre[y]=x;
rank[x]+=rank[y];
}
else
{
pre[x]=y;
rank[y]+=rank[x];
}
}