并查集的实现主要有两个功能:
1.find(x),返回x的根结点,可以将其想象为一颗树。
2.union(x,y),将x,y融合为一颗树.
具体实现有
1.parent[x]:指的是x的根结点.
2.rank[x]:指以x为根结点时,从叶子到根结点的最大距离(hops)。
为了使union方便,在进行union(x,y)操作时,选择将rank小的树的根结点改为rank较大树的根结点。
仅仅改变rank小的根结点的parent。
3.union的时候,大部分的rank不变,只有在融合两个具有相同的rank值时,被融合的rank那一方才会加1.
代码如下:
/************并查集**********/
class UnionFind
{
public:
UnionFind(int len)//初始化
{
length = len;
rank.resize(len);
parent.resize(len);
for(int i = 0; i < length; i++)
{
rank[i] = 0;
parent[i] = i;
}
}
/********判断能否融合*****/
bool unite(int x, int y)
{
int a = find(x);
int b = find(y);
if(a == b)
{
return false;
} else {
if(rank[a] == rank[b])
{
parent[a] = b;
rank[b]++; //只有两棵树的rank相等时候,union的时候某一方的rank不变
} else if(rank[a] < rank[b]) {
parent[a] = b;
} else {
parent[b] = a;
}
}
return true;
}
int find(int x) //返回根结点
{
if(parent[x] == x) //满足parent[x] == x 时候返回,找到根结点
{
return x;
} else {
return find(parent[x]);
}
}
public:
vector<int> rank;
//rank[x] = the max number of hops from a leaf to x
vector<int> parent; //根结点
int length;
};
并查集的优化还有path compression的优化方案。在此不在详述。