Revisión de la estructura de datos - búsqueda de unión

La búsqueda de unión es una representación de conjunto simple que admite las siguientes tres operaciones:

(1) inicialización;

(2) fusionar conjuntos disjuntos;

(3) Encuentre el subconjunto donde x se encuentra en el conjunto s y devuelva el nodo raíz del subconjunto;

1. Inicialización de búsqueda de unión

#define SIZE 100
int UFSets[SIZE];

//并查集的初始化
void initial(int s[])
{
	for(int i=0;i<SIZE;i++)
	{
		s[i]=-1;
	}
 } 

2. La operación de búsqueda de la búsqueda de unión

 //并查集的“查”操作(函数在并查集s中查找并返回包含元素x的树的根)
 int find(int s[],int x)
 {
 	while(s[x]>=0)
 	x=s[x];
 	return x;     //根的s[]小于0 
  } 

3. Operación de unión no optimizada para búsqueda de unión

  //并查集的"并"操作(函数求两个不相交子集合的并集)
  void Union(int s[],int root1,int root2)
  {
  	if(root1==root2)  //同一集合没必要合并 
  	return ;
  	s[root2]=root1;   //将根root2连接到根root1下面 
   } 

Dado que la búsqueda de unión no está optimizada, después del análisis, la peor complejidad temporal del algoritmo está relacionada con la altura del árbol, que es O(n);

4. Optimización de la búsqueda de unión

//优化后的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; 
	}
 } 

Optimice la búsqueda de unión y trate de no hacer que el árbol sea "delgado y alto", así que elija fusionar el árbol pequeño debajo del árbol grande y almacene el número opuesto del árbol de puntos de resumen del árbol en la matriz correspondiente al nodo raíz . En este momento, por inducción matemática, se puede saber que la altura del árbol <=logn+1, la complejidad del tiempo es O(logn). 

5. La optimización definitiva de la búsqueda de unión 

Optimice la operación de búsqueda, busque primero el nodo raíz y luego cuelgue todos los nodos en la ruta de búsqueda debajo del nodo raíz.

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;       //返回根节点编号 
} 

La complejidad temporal de find es O(a(n)). 

Supongo que te gusta

Origin blog.csdn.net/m0_51769031/article/details/125252321
Recomendado
Clasificación