A pesquisa de união é uma representação de conjunto simples que suporta as três operações a seguir:
(1) inicialização;
(2) Mesclar conjuntos disjuntos;
(3) Encontre o subconjunto onde x está localizado no conjunto s e retorne o nó raiz do subconjunto;
1. Inicialização da pesquisa de união
#define SIZE 100
int UFSets[SIZE];
//并查集的初始化
void initial(int s[])
{
for(int i=0;i<SIZE;i++)
{
s[i]=-1;
}
}
2. A operação de localização da pesquisa de união
//并查集的“查”操作(函数在并查集s中查找并返回包含元素x的树的根)
int find(int s[],int x)
{
while(s[x]>=0)
x=s[x];
return x; //根的s[]小于0
}
3. Operação de união não otimizada para pesquisa de união
//并查集的"并"操作(函数求两个不相交子集合的并集)
void Union(int s[],int root1,int root2)
{
if(root1==root2) //同一集合没必要合并
return ;
s[root2]=root1; //将根root2连接到根root1下面
}
Como a busca união não é otimizada, após análise, a pior complexidade de tempo do algoritmo está relacionada à altura da árvore, que é O(n);
4. Otimização da busca sindical
//优化后的Union,让小树合并到大树下面,确保树的高度不会增加
//此时根结点的数组中存放的是该棵树的总结点树的相反数 (即负数)
void Union(int s[],int root1,int root2)
{
if(root1==root2)
return ;
if(s[root1]<s[root2]) //说明根root1的结点比较多,是棵大树,需要把root2合并到root1
{
s[root1]+=s[root2]; //大树的结点总数增加
s[root2]=root1; //更改小树的根节点
}
else
{
s[root2]+=s[root1];
s[root1]=root2;
}
}
Otimize a pesquisa de união e tente não tornar a árvore "fina e alta", então opte por mesclar a árvore pequena sob a árvore grande e armazene o número oposto da árvore do ponto de resumo da árvore na matriz correspondente ao nó raiz . Neste momento, usando indução matemática, pode-se saber que a altura da árvore <=logn+1; a complexidade de tempo é O(logn).
5. A otimização final da pesquisa de união
Otimize a operação de localização, localize primeiro o nó raiz e, em seguida, pendure todos os nós no caminho de pesquisa sob o nó raiz.
int find(int s[],int x)
{
int root=x;
while(s[root]>=0) //找到根节点
{
root=s[root];
}
while(x!=root) //压缩路径,将查找路径上的所有结点都挂到根节点下
{
int t=s[x]; //保存x的父节点
s[x]=root; //修改x的父节点使其指向根节点
x=t; //继续往上修改结点
}
return root; //返回根节点编号
}
A complexidade de tempo de find é O(a(n)).