对不相交集合进行俩种操作:
1. 检索某元素属于哪个集合
2. 合并两个集合
我们最常用的数据结构是并查集的森林实现,也就是说,在森林中,每棵树代表一个集合,用树根来标识一个集合,树的形态不重要,重要的是每棵树有哪些元素。
查找操作
查找一个元素v很简单,只需要顺着叶子到根节点的路径找到u所在的根节点,然后把v到u的路径上面的结点的父节点都设置为根节点,这样减少了查找的次数(路径压缩)。
合并操作
为了把两个集合s1和s2并起来,只需要把s1的根的父亲设置为s2的根节点,我们可以做一个优化,将深度小的合并成为深度大的子树,这样子查找的次数少些。
/* 初始化集合*/
void Make_Set(int x)
{
father[x] = x; //根据实际情况指定的父节点可变化
rank[x] = 0; //根据实际情况初始化秩也有所变化
}
/* 查找x元素所在的集合,回溯时压缩路径*/
int Find_Set(int x)
{
if (x != father[x])
{
father[x] = Find_Set(father[x]); //这个回溯时的压缩路径是精华
}
return father[x];
}
//将秩小的合并到秩大的集合中
void Union(int x, int y)
{
x = Find_Set(x);
y = Find_Set(y);
if (x == y) return;
if (rank[x] > rank[y])
{
father[y] = x;
}
else
{
if (rank[x] == rank[y])
{
rank[y]++;
}
father[x] = y;
}
}