定义
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。
主要由一个整型数组
p
r
e
[
]
pre[]
pre[]和函数
f
i
n
d
(
)
find()
find()、
j
o
i
n
(
)
join()
join()构成。
数组
p
r
e
[
]
pre[]
pre[]记录了每个点的前驱节点是谁。
函数
f
i
n
d
(
x
)
find(x)
find(x) 用于查找指定节点
x
x
x属于哪个集合。
函数
j
o
i
n
(
x
,
y
)
join(x,y)
join(x,y)用于合并
x
x
x和
y
y
y。
find()函数
首先定义一个
p
r
e
pre
pre数组,记录着
i
i
i的上级是谁,例如
p
r
e
[
3
]
=
4
pre[3]=4
pre[3]=4,表示3的上级是4,若自己的上级是自己,则表示它是顶级了。
f
i
n
d
(
x
)
find(x)
find(x)函数的目的就是查找
x
x
x的最上级。
int find(int x)
{
while(pre[x] != x) //若x的上级不是自己,则说明还没找到
x = pre[x]; //x继续找他的上级,直到找到最上级为止
return x; //找到了
}
join()函数
j o i n ( x , y ) join(x,y) join(x,y)是将x当作y的上级或者y当作x的上级。
void join(int x,int y)
{
int fx=find(x), fy=find(y); //找到x与y的上级
if(fx != fy) //发现并不是同一个上级
pre[fx]=fy; //将y当作x的上级
}
总结:
附上抄袭代码一份(侵删)
const int N=1005 //指定并查集所能包含元素的个数(由题意决定)
int pre[N]; //存储每个结点的前驱结点
int rank[N]; //树的高度
void init(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; //递归出口:x的上级为 x本身,则 x为根结点
return find(pre[x]); //递归查找
}
int find(int x) //改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点
return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx
}
bool isSame(int x, int y) //判断两个结点是否连通
{
return find(x) == find(y); //判断两个结点的根结点(即代表元)是否相同
}
bool join(int x,int y)
{
x = find(x); //寻找 x的代表元
y = find(y); //寻找 y的代表元
if(x == y) return false; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,返回 false,表示合并失败;否则,执行下面的逻辑
if(rank[x] > rank[y]) pre[y]=x; //如果 x的高度大于 y,则令 y的上级为 x
else //否则
{
if(rank[x]==rank[y]) rank[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1
pre[x]=y; //让 x的上级为 y
}
return true; //返回 true,表示合并成功
}