Conjunto de cheques sindicales y su sencilla aplicación

inserte la descripción de la imagen aquí

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~9están representados por números enteros y el conjunto de búsqueda de unión se puede expresar de la siguiente manera: inserte la descripción de la imagen aquí
  • 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.:inserte la descripción de la imagen aquí

    • 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 ==:inserte la descripción de la imagen aquí

2. Realización del control sindical

  • La configuración del estado inicial de la búsqueda de unión:inserte la descripción de la imagen aquí
  • 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

LeetCoed: LCR 116. Número de provincias

  • 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 dfsun bfsalgoritmo 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 vectory y finalmente regreselambdaY 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;
    }
};

LeetCode: 990. Satisfabilidad de la ecuación

  • Este es también un problema de división de clases de equivalencia: establecer una relación de mapeo entre 0~25cada número y a~zveintisé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;
    }
};

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_73470348/article/details/132420452
Recomendado
Clasificación