一、内容
由一个整型数组pre[]和两个函数find(),join()构成
二、作用
求连通分支数
三、find函数作用与实现
a、作用:找出指定x所在集合的boss(根节点)。
b、实现:
int find(int x){
while(pre[x]!=x)
x=pre[x];
retuen x;
}
四、join函数作用于实现
a、作用:让指定的两个数x,y所在集合的其中一个boss成为另外一个boss,使这两个集合合并为同一个集合。
b、实现:
void join(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy)
pre[fx]=fy;
}
注:可通过rank函数优化合并集合函数
void Union(int i,int j){
i=find(i);
j=find(j);
if(i==j) return;
if(rank[i]>rank[j]) pre[j]=i;
else{
if(rank[i]==rank[j]) rank[j]++;
pre[i]=j;
}
}
五、路径压缩算法的含义与实现
a、含义:使指定x的上一级直接为boss,提高效率
b、实现:
int find(int x){
if(pre[x]==x)
return x;
return pre[x]=find(pre[x]);
}
总结
1、用集合中的某个元素来代表这个集合,该元素称为集合的代表元
2、对于每一个元素pre[x]指向x在树形结构上的父亲节点。(若x为根节点,则pre[x]=x)
3、判断两个元素是否为同一个集合,只要看他们代表元是否相同即可
4、一般来说,并查集分为三个操作:初始化,查找根节点,合并集合
初始化如下(某个元素上一级就是自己)
void Make_pre(int i){
pre[i]=i;
}
5、汇总代码
const int N=100
int pre[N];
int rank[N]; //树高度
void Make_pre(int n){ //初始化函数,对录入的n个结点进行初始化
for(int i=0;i<n;i++){
pre[i]=i; //每个结点的上一级都是自己
rank[i]=1; //每个结点树的高度都是1
}
}
int find(int x){ //查找结点x的根节点
if(pre[x]==x) return x;
return pre[x]=find(pre[x]); //先找到根节点,然后pre[x]=根节点
}
bool is_same(int x,int y){ //判断结点是不是连通
return find(x)==find(x);
}
bool unite(int x,int y){ //令y的根结点的上级为x
x=find(x);
y=find(y);
if(x==y) return false;
if(rank[x]>rank[y]) pre[y]=x;
else{
if(rank[x]==rank[y]) rank[y]++;
pre[x]=y;
}
return true;
}