Directorio de artículos
1. Comprobar y cobrar
-
y comprobadoestructura lógica: por múltiplesdesconectadodeÁrbol de múltiples horquillasconstituidobosque(Un árbol de múltiples ramas es un bosquecomponente conectado)
- Los elementos (nodos de árbol) del conjunto de búsqueda de unión
0~9
están representados por números enteros y el conjunto de búsqueda de unión se puede expresar de la siguiente manera:
- Los elementos (nodos de árbol) del conjunto de búsqueda de unión
-
y comprobadoestructura de almacenamiento físico: El control sindical generalmente adoptaestructura secuenciallograr consubíndice de matrizexpresarY revisa los elementos,elemento de matrizpara grabaciónY comprobar la relación entre los elementos del conjunto.:
- comoY revisa los elementoscorrespondienteelemento de matrizparanumero negativo, significa que ely comprobar elementoparaLa raíz de un árbol de múltiples ramas sin predecesores,el valor absoluto de un número negativoexpresarEl número de elementos del árbol de múltiples bifurcaciones (componentes conectados del conjunto de búsqueda de unión)
- comoY revisa los elementoscorrespondienteelemento de matrizparanúmero no negativo,estenúmero no negativoentonces significaEl nodo predecesor de los elementos del conjunto de búsqueda de unión.
-
La operación comúnmente utilizada de la estructura de datos de búsqueda de unión es el algoritmo de fusión entre == (componentes conectados) múltiples árboles ==:
2. Realización del control sindical
- La configuración del estado inicial de la búsqueda de unión:
- Implementación de código simple:
#include <iostream>
#include <vector>
#include <string>
//采用适配器模式实现并查
class UnionFindSet
{
public:
//构造函数参数为并查集中的元素个数,并查集的初始状态为size颗树构成的森林(size个连通分量)
UnionFindSet(size_t size)
:_SetMap(size,-1)
{
}
//给定一个并查集元素找到其所在的(连通分量)多叉树的根结点
size_t FindRoot(int Node) const throw(std :: string)
{
//越界检查
if (Node < 0 || Node >= _SetMap.size())throw "Label out of range";
while (_SetMap[Node] >= 0)
{
Node = _SetMap[Node];
}
return static_cast<size_t>(Node);
}
//给定两个并查集元素,将它们所在的(连通分量)多叉树进行合并运算
void Union(int Node1, int Node2) throw(std::string)
{
//越界检查
if (Node1 < 0 || Node1 > _SetMap.size()|| Node2 < 0 || Node2 > _SetMap.size())
throw "Label out of range";
//先找到两个元素所在的(连通分量)多叉树的根
size_t root1 = FindRoot(Node1);
size_t root2 = FindRoot(Node2);
//进行多叉树合并操作
if (root1 != root2)
{
_SetMap[root1] += _SetMap[root2];
_SetMap[root2] = static_cast<int>(root1);
}
}
//计算并查集中多叉树的颗数(连通分量的个数)
size_t SetCount() const noexcept
{
//并查集中多叉树的颗数就是vector中负数元素的个数
size_t count = 0;
for (auto e : _SetMap)
{
if (e < 0)++count;
}
return count;
}
private:
std::vector<int> _SetMap;
};
- Y el conjunto de verificación es una especie de frecuenciautilizado para dividir clases de equivalenciaLa estructura de datos: basada en la estructura lógica de árbol, conUn árbol de múltiples bifurcaciones (un componente conectado)expresaruna clase de equivalencia, múltipledesconectadoSe utiliza un bosque de árboles de múltiples ramas (componentes conectados) para representarconjunto de clases de equivalencia, el uso de conjuntos de búsqueda de unión puede resolver bien los problemas de división y conteo de clases de equivalencia (es decir, el problema de resolver los componentes conectados de gráficos)
3. Aplicación básica de la búsqueda sindical
- Esta pregunta es unaconjunto de clases de equivalenciadePreguntas para construir y contar, se puede resolver utilizando la búsqueda de unión (en el títulorelación conectadaes un parientemisma naturaleza provincialrelación de equivalencia)
- La esencia del problema se puede resumir como:Toma la ciudad como elemento.de acuerdo conrelación conectadaLa estructura del gráfico formado.El número de árboles de expansión mínimos.(Es decir, la cantidad de componentes conectados), puede usar
dfs
unbfs
algoritmo transversal, y aquí hay una manera de usar la búsqueda conjunta. - Cree una búsqueda de unión simple con la ayuda de expresiones
vector
y y finalmente regreselambda
Y verifique la cantidad de árboles múltiples en el conjunto.:
class Solution
{
public:
int findCircleNum(vector<vector<int>>& isConnected)
{
//创建简易的并查集
vector<int> UnionSet(isConnected.size(),-1);
//定义Find函数,根据结点找到多叉树的根
auto Find = [&UnionSet](int Node){
while(UnionSet[Node] >=0)
{
Node = UnionSet[Node];
}
return Node;
};
for(int i = 0; i < isConnected.size(); ++i)
{
for(int j = i+1; j < isConnected.size(); ++j)
{
if(isConnected[i][j] == 1)
{
//多叉树合并
int root1 = Find(i);
int root2 = Find(j);
if(root1 != root2)
{
UnionSet[root1] += UnionSet[root2];//这句代码用于修改结点计数,此题中可以不加
UnionSet[root2] = root1;
}
}
}
}
int count = 0;
//统计并查集中多叉树的个数
for(auto e : UnionSet)
{
if(e < 0 ) ++count;
}
return count;
}
};
- Este es también un problema de división de clases de equivalencia: establecer una relación de mapeo entre
0~25
cada número ya~z
veintiséis letras, de acuerdo con elEquivalenciaConstruya y verifique:
class Solution
{
public:
bool equationsPossible(vector<string>& equations)
{
vector<int> UionSet(26,-1);
auto FindRoot = [&UionSet](int Node){
while(UionSet[Node] >= 0)
{
Node = UionSet[Node];
}
return Node;
};
//先遍历等式方程中的字母,在并查集中将它们归类到各个多叉树中(构建相等关系等价类集合)
for(auto str : equations)
{
//遇到等式,等式两边字母应该属于并查集中同一颗多叉树
if(str[1] == '=')
{
int root1 = FindRoot(str[0]-'a');
int root2 = FindRoot(str[3]-'a');
if(root1 != root2)
{
UionSet[root1] += UionSet[root2];
UionSet[root2] = root1;
}
}
}
//再处理不等式方程,检验相容性
for(auto str : equations)
{
//遇到不等式,不等式两边字母不能属于并查集中同一颗多叉树
if(str[1] == '!')
{
int root1 = FindRoot(str[0]-'a');
int root2 = FindRoot(str[3]-'a');
if(root1 == root2)
{
return false;
}
}
}
return true;
}
};