并查集主要用来解决判断两个元素是否同属一个集合,以及把两个集合合并成一个集合的问题。
具体实现:
分为搜索和合并两个运算。为了方便并查集的描述与实现,通常把先后加入到一个集合中的元素表示成一个树结构,并用根节点的序号来代表这个集合。因此定义一个parent[n]的数组,parent[i]中存放的是结点i所在的树中结点i父亲结点的序号。约定:如果结点i的父结点是负数,则表示i就是所在集合的根节点,因为在集合中没有结点的序号是负的;并且用负的绝对值作为这个集合所含的节点数。初始时,所有结点的parent均为-1.
代码如下
void UFset()///初始化
{
for(i=0;i<n;i++)
parent[i]=-1;
}
int Find(int x)///查找并且返回结点x所属集合的根节点
{
int s;///s记录x的根节点
for(s=x;parent[s]>=0;s=parent[s]);///定位x;直到出现节点数小于零,循环结束;定位下一个
while(s!=x)///优化方案——压缩路径,使后续的查找操作加速
{
int temp=parent[x]; ///记录下一个
parent[x]=s; ///改变这一个
x=temp; ///定位下一个
}
return s;
}
void Union(int R1,int R2)
{
int r1=Find(R1);
int r2=Find(R2);
int temp=parent[r1]+parent[r2];
if(parent[r1]>parent[r2])///优化方案——加权法则
{
parent[r1]=r2;///将结点r1作为所在的树作为r2的子树
parent[r2]=temp;///更新根节点r2的parent[]的值
}
else
{
parent[r2]=r1;
parent[r1]=temp;
}
}