Notas de algoritmo - Comprobación de unión

Notas de algoritmo - Comprobación de unión

El conjunto de verificación de unión es una estructura de datos similar a un árbol que se utiliza para tratar los problemas de combinación y consulta de algunos conjuntos disjuntos (los llamados unión y verificación).

Hay muchos bloggers que han escrito muy bien sobre la explicación de la colección y la colección. Aquí me refiero principalmente a este artículo, y verifico la colección .

definición

El conjunto de búsqueda de unión es en realidad una estructura de árbol, que se puede usar para consultar el número de ramas conectadas, y aquellas que pertenecen a la misma rama conectada están en el mismo número

variable principal

pre[]: registra el nodo predecesor del
rango de nodos[]: registra la altura del
conteo de nodos: registra el número de ramas conectadas

función principal

init(): inicializa
join(x, y): fusiona los nodos x, y
find(x): encuentra el nodo raíz del árbol donde se encuentra el nodo x

definición de función

1.buscar()

Aquí siempre se encuentra el nodo raíz a través de find. Cuando pre[x]=x, se encuentra el nodo raíz.
Si no espera, se puede buscar. Aquí, modifique el pre[x] al volver a comprimir el ruta de búsqueda Específicamente, el principio se menciona en el blog al comienzo del artículo.

    int find(int x)
    {
    
    
        if (pre[x] == x)
            return x;
        else
            return pre[x] = find(pre[x]);
    }

2.unirse()

Para conectar dos nodos, simplemente conecte el nodo raíz del árbol donde se encuentra un nodo al nodo raíz del otro árbol.

  1. Primero, determine si los dos nodos pertenecen al mismo árbol, es decir, determine si los nodos raíz de los dos nodos son iguales, si son iguales, los dos nodos están conectados y regresan directamente.
  2. Aquí queremos conectar un árbol con una altura pequeña a un árbol con una altura grande, para que la altura del árbol conectado pueda reducirse, así que primero juzgue las alturas de los nodos raíz de los dos árboles respectivamente. no es igual, conecte el más pequeño a En el lado grande, el rango original permanece sin cambios después de la conexión. Si la altura de los dos árboles es la misma, la altura del árbol conectado debe aumentarse en 1. Aquí puede dibujar un imagen para verlo, que es más fácil de entender.
  3. Después de conectar los dos árboles, el número total de componentes conectados se reduce en 1
void join(int x, int y)
    {
    
    
        x = find(x);
        y = find(y);

        if (x == y)
            return;
        if (rank[x] < rank[y])
        {
    
    
            pre[x] = y;
        }
        else
        {
    
    
            if (rank[x] == rank[y])
            {
    
    
                pre[x] = y;
                rank[y]++;
            }
            else
            {
    
    
                pre[y] = x;
            }
        }
        count--;
    }

3. inicializar()

Con respecto a la función init(), es principalmente la inicialización de pre[] y rank[].Puedes ver el ejemplo al final del artículo para profundizar tu comprensión.

ejemplo

La única diferencia está en la inicialización del conjunto concatenado para diferentes temas, y otras funciones son básicamente las mismas. Los siguientes dos ejemplos muestran principalmente cómo inicializar el conjunto concatenado. El código usa la plantilla que se acaba de escribir arriba.

547. Número de Provincias

Código:

class UnionFind
{
    
    
private:
    vector<int> pre;
    vector<int> rank;
    int count = 0;

public:
    UnionFind(vector<vector<int>> isConnected)
    {
    
    
        int n = isConnected.size();
        for (int i = 0; i < n; i++)
        {
    
    
            pre.push_back(i);
            rank.push_back(1);
            count++;
        }
    }
    int find(int x)
    {
    
    
        if (x == pre[x])
            return x;
        else
            return pre[x] = find(pre[x]);
    }
    void join(int x, int y)
    {
    
    
        x = find(x);
        y = find(y);
        if (x == y)
            return;
        if (rank[x] < rank[y])
            pre[x] = y;
        else
        {
    
    
            if (rank[x] == rank[y])
            {
    
    
                pre[x] = y;
                rank[y]++;
            }
            else
                pre[y] = x;
        }
        count--;
        return;
    }
    int getCount()
    {
    
    
        return count;
    }
};
class Solution
{
    
    
public:
    int findCircleNum(vector<vector<int>> &isConnected)
    {
    
    
        UnionFind uf(isConnected);
        int n = isConnected.size();
        for (int i = 0; i < n; i++)
        {
    
    
            for (int j = 0; j < n; j++)
            {
    
    
                if (isConnected[i][j])
                    uf.join(i, j);
            }
        }
        return uf.getCount();
    }
};

200. Número de islas

Código:

class UnionFind
{
    
    
private:
    vector<int> pre;
    vector<int> rank;
    int count = 0;

public:
    UnionFind(vector<vector<char>> grid)
    {
    
    
        int n = grid.size();
        int m = grid[0].size();

        for (int i = 0; i < n; i++)
        {
    
    
            for (int j = 0; j < m; j++)
            {
    
    
                if (grid[i][j] == '1')
                {
    
    
                    pre.push_back(i * m + j);
                    rank.push_back(1);
                    count++;
                }
                else
                {
    
    
                    pre.push_back(-1);
                    rank.push_back(-1);
                }
            }
        }
    }

    int find(int x)
    {
    
    
        if (pre[x] == x)
            return x;
        else
            return pre[x] = find(pre[x]);
    }

    void join(int x, int y)
    {
    
    
        x = find(x);
        y = find(y);

        if (x == y)
            return;
        if (rank[x] < rank[y])
        {
    
    
            pre[x] = y;
        }
        else
        {
    
    
            if (rank[x] == rank[y])
            {
    
    
                pre[x] = y;
                rank[y]++;
            }
            else
            {
    
    
                pre[y] = x;
            }
        }
        count--;
    }

    int getCount()
    {
    
    
        return count;
    }
};

class Solution
{
    
    
private:
    int fx[4][2] = {
    
    {
    
    -1, 0}, {
    
    0, 1}, {
    
    1, 0}, {
    
    0, -1}};

public:
    int numIslands(vector<vector<char>> &grid)
    {
    
    
        int n = grid.size();
        int m = grid[0].size();
        UnionFind uf(grid);

        for (int i = 0; i < n; i++)
        {
    
    
            for (int j = 0; j < m; j++)
            {
    
    
                if (grid[i][j] == '1')
                {
    
    
                    grid[i][j] = '0';
                    for (int k = 0; k < 4; k++)
                    {
    
    
                        int newi = i + fx[k][0];
                        int newj = j + fx[k][1];
                        if (newi >= 0 && newi < n && newj >= 0 && newj < m && grid[newi][newj] == '1')
                        {
    
    
                            uf.join(i * m + j, newi * m + newj);
                        }
                    }
                }
            }
        }
        return uf.getCount();
    }
};

Supongo que te gusta

Origin blog.csdn.net/shn111/article/details/123281499
Recomendado
Clasificación