Notas de estudio de C ++ (dos) ———— Tabla hash (Hash)

1. Tabla hash (tabla hash)

Hay tres métodos de búsqueda principales en el campo de búsqueda, búsqueda de tabla lineal, búsqueda de árbol (similar a BST) y búsqueda de tabla hash, que también se denomina tabla hash.

  • Función hash
  • Tabla de picadillo
  • registro de datos

La tabla hash es nuestra función. Para cada valor de clave de entrada, se asigna una dirección de almacenamiento única, y la dirección eventualmente almacenará nuestros datos.

  • La función hash es un mapeo, y el núcleo del diseño es diseñar una función hash perfecta para minimizar los conflictos.
  • Función hash: devuelve la dirección de memoria única correspondiente para cualquier valor clave para que insertemos, eliminemos y almacenemos datos
  • Conflicto: al igual que una función periódica aparece en una función, también nos encontraremos con una situación en la que podemos obtener la misma dirección de memoria para diferentes palabras clave. Esto es un conflicto. Las dos palabras clave correspondientes se llaman Sinónimo.
  • Tabla hash: la tabla hash es para mapear un conjunto de palabras clave a un conjunto de direcciones continuo (intervalo) de acuerdo con la función hash que configuramos y el método de resolución de conflictos que establecemos, y las palabras clave están en la dirección. Al igual que la ubicación de almacenamiento registrada en la tabla, esto se llama tabla hash. Este proceso de mapeo también se llama establecimiento de una tabla hash o hash, y la ubicación de almacenamiento que obtenemos se llama dirección hash o dirección hash.

En resumen, encontraremos dos núcleos de la tabla hash:

1. Construya un hash: (Construya una función hash) Cree un mapeo basado en la función hash.

2. Manejo de conflictos: Es difícil para nosotros diseñar una función hash sin conflictos, por lo que es muy necesario tratar los conflictos.

En segundo lugar, el método de construcción de la tabla hash.

La tecnología hash consiste en establecer una cierta relación correspondiente f entre la ubicación de almacenamiento del registro y sus palabras clave. Cada clave de palabra clave corresponde a una ubicación de almacenamiento f (clave). Al buscar, encontrar un valor dado de acuerdo con esta relación correspondiente. Si la asignación de teclas f (tecla) existe en el conjunto de búsqueda, debe estar en la posición de f (tecla). Llamamos a esta correspondencia f una función hash, también conocida como función hash (hash). La tecnología hash se utiliza para almacenar registros en un espacio de almacenamiento, este espacio continuo se denomina tabla hash o tabla hash (Hash-Table).

2.1 Método de direccionamiento directo

El método de direccionamiento directo utiliza la siguiente fórmula

f (tecla) = a * tecla + b, a y b son constantes

Por ejemplo, si cuenta el año y el mes de nacimiento, puede usar f (clave) = clave-1990 para calcular la dirección hash.

Dirección h (clave) Año de nacimiento (clave) Número (atributo)
0 1990 12,85 millones
1 1991 12,81 millones
2 1992 12,8 millones
\ cdots \ cdots \ cdots
10 2000 12,5 millones
\ cdots \ cdots \ cdots
21 2011 11,8 millones

2.2 Método de dividir y dejar el resto

Este método es el método de construcción de función hash más comúnmente utilizado. La fórmula hash para una longitud de tabla de m es:
f (clave) = clave mod p (p <= m)

  habla a

h (tecla)

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis

Palabras clave

   llave

34 18 2 20     23 7 42   27 11   30   15  
  • Aquí: p = Tablesize = 17
  • Generalmente, p es primo 

2.3 Método de análisis digital

Analice los cambios de las palabras clave digitales en cada bit y tome los bits más aleatorios como dirección hash. Aquí usamos un número de teléfono móvil como ejemplo. El número de teléfono móvil es una cadena de caracteres. Generalmente hablando, los últimos 4 dígitos son el número de usuario real.

Por ejemplo: tome los últimos 4 dígitos de la tecla del número de teléfono móvil de 11 dígitos como dirección: la
función hash es: h (tecla) = atoi (tecla + 7) (tecla char *)

2.4 Método de plegado

Divida la palabra clave en varias partes con el mismo número de bits y luego superponga:

Tales como: 56793542

2.5 Método de toma de cuadrados

 Tales como: 56793542

Tres, métodos de resolución de conflictos

Formas comunes de lidiar con conflictos:
1. Cambiar ubicación: método de dirección abierta

2. Los objetos en conflicto en la misma ubicación se organizan juntos: método de dirección en cadena

3.1 Ley de direcciones abiertas

Una vez que ocurre un conflicto (la dirección ya tiene otros elementos), se tomará para buscar otra dirección vacía de acuerdo con ciertas reglas. Si ocurre el i-ésimo conflicto, la siguiente dirección a probar aumentará d_ {i}. La fórmula básica es:
h_ {i} \ izquierda (tecla \ derecha) - (h \ izquierda (tecla \ derecha) + d_ {i})  mod TableSize (1 < = i <TableSize)

Esto d_ {i}determina diferentes esquemas de resolución de conflictos: detección lineal, detección de cuadrados y hash doble. Estos son los distintos métodos a su vez:

3.1.1 Método de detección lineal

El método de detección lineal sondea cíclicamente la siguiente dirección de almacenamiento con una secuencia incremental de 1, 2, ..., (TableSize-1).

[Ejemplo 1] Sea la secuencia de palabras clave 47, 7, 29, 11, 9, 84, 54, 20, 30 y la longitud de la tabla hash

TableSize = 11 (factor de llenado \ alpha = \ frac {9} {13} \ aproximadamente 0,69), la función hash es: h (clave) = clave mod 11. Utilice el método de detección lineal para tratar el conflicto, enumere la tabla hash después de la inserción sucesiva y estime el rendimiento de la búsqueda.

[Solución] La dirección hash preliminar se muestra en la siguiente tabla:

关键词(key)      47 7 29 11 9 84 54 20 30
散列地址h(key)    3 7  7  0 9  7 10  9  8

Se puede ver que hay conflictos en las direcciones hash de varias palabras clave; consulte la tabla a continuación para obtener más detalles.

关键词(key)      47 7 29 11 9 84 54 20 30
散列地址h(key)    3 7  7  0 9  7 10  9  8
冲突次数            0 0  1  0 0  3  1  3  6

El proceso específico de construcción de la tabla hash se puede representar mediante el siguiente diagrama

operando habla a 0 1 2 3 4 5 6 7 8 9 10 11 12 Descripción
Insertar 47       47                   No conflicto
Insertar 7       47       7           No conflicto
Insertar 29       47       7 29         d_ {1} = 1
Insertar 11 11     47       7 29         No conflicto
Insertar 9 11     47       7 29 9       No conflicto
Insertar 84 11     47       7 29 9 84     d_ {3} = 3
Insertar 54 11     47       7 29 9 84 54   d_ {1} = 1
Insertar 20 11     47       7 29 9 84 54 20 d_ {3} = 3
Insertar 30 11 30   47       7 29 9 84 54 20 d_ {6} = 6

 A continuación se muestra un análisis del rendimiento de búsqueda de la tabla hash. En general, existen dos métodos para el rendimiento de búsqueda de la tabla hash.

1. Duración de búsqueda promedio satisfactoria (ASL)

2. Duración de búsqueda promedio sin éxito (ASLu)

Para la pregunta anterior, el número de conflictos de direcciones hash es

关键词(key)      0  1  2  3  4  5  6  7  8   9  10  11  12
散列地址h(key)   11 30    47          7  28  9  84  54  20
冲突次数           0  6     0           0  1   0  3   1   3

ASL: el número promedio de búsquedas y comparaciones de palabras clave en la tabla de búsqueda (el número de conflictos más 1)

ASL = (1 + 7 + 1 + 1 + 2 + 1 + 4 + 2 + 4) / 9 = \ aprox23/9 2.56

ASLu: número promedio de búsquedas de palabras clave que no están en la tabla hash (sin éxito)

Método general: divide las palabras clave que no están en la tabla hash en varias categorías.

Tales como: según la clasificación del valor h (clave)

ASLu = (3 + 2 + 1 + 2 + 1 + 1 + 1 + 9 + 8 + 7 + 6) / 11 = \ aprox41/11 3,73

3.1.2 Método de detección de cuadrados

El método de detección de cuadrados utiliza una secuencia incremental 1 ^ {2}, - 1 ^ {2}, 2 ^ {2}, - 2 ^ {2}, \ cdots \ cdots, q ^ {2}y q <= [TableSize / 2]bucles para sondear la siguiente dirección de almacenamiento. Todavía use [Ejemplo 1], los conflictos obtenidos son los siguientes

Palabra clave 47 7 29 11 9 84 54 20 30
Dirección hash h (tecla) 3 7 7 0 9 7 10 9 8
Numero de conflictos 0 0 1 0 0 2 0 3 3

 ASL = (1 + 1 + 2 + 1 + 1 + 3 + 1 + 4 + 4) / 9 = 18/9 = 2

operando habla a 0 1 2 3 4 5 6 7 8 9 10 Descripción
Insertar 47       47               No conflicto
Insertar 7       47       7       No conflicto
Insertar 29       47       7 29     d_ {1} = 1
Insertar 11 11     47       7 29     No conflicto
Insertar 9 11     47       7 29 9   No conflicto
Insertar 84 11     47     84 7 29 9   d_ {2} = - 1
Insertar 54 11     47     84 7 29 9 54 No conflicto
Insertar 20 11   20 47     84 7 29 9 54 d_ {3} = 4
Insertar 30 11 30 20 47     84 7 29 9 54 d_ {3} = 4

3.2 Método de dirección en cadena 

El método de dirección en cadena es almacenar todas las palabras clave en conflicto en la posición correspondiente en la misma lista enlazada individualmente. 

[Ejemplo 2] Sea la secuencia de teclas 47, 7, 29, 11, 16, 92, 22, 8, 3, 50, 37, 89, 94, 21, y la función hash es h (tecla) = tecla mod 11 , Utilice el método de enlace de separación para manejar conflictos.

[Una pregunta por día]

Suma de dos números

Dado un número de matriz de enteros y un objetivo de valor objetivo, busque los dos enteros cuya suma sea el valor objetivo en la matriz y devuelva sus subíndices de matriz.

Puede suponer que cada entrada solo corresponderá a una respuesta. Sin embargo, el mismo elemento de la matriz no se puede utilizar dos veces.

Ejemplo:

给定 nums = [2,7,11,15],target = 9
因为 nums[0] + nums[1] = 2 + 7 =9
所以返回[0,1]

Método 1: enumeración violenta

【responder】

Ideas y métodos:

La forma más fácil de pensar es enumerar cada número x en la matriz para encontrar si target-x existe en la matriz.

Cuando usamos el método de atravesar toda la matriz para encontrar el objetivo-x, debemos tener en cuenta que todos los elementos anteriores a x se han emparejado con x, por lo que no es necesario hacer coincidir. Cada elemento no se puede usar dos veces, por lo que solo necesitamos buscar target-x en el elemento después de x.

Código:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0];
    }
}

Método 2: tabla hash

Ideas y algoritmos:

Tenga en cuenta que la razón de la alta complejidad temporal del Método 1 es que la complejidad temporal de encontrar el objetivo-x es demasiado alta. Por lo tanto, necesitamos una mejor manera de encontrar rápidamente si hay un elemento de destino en la matriz. Si existe, necesitamos encontrar su índice.

Usando una tabla hash, la complejidad temporal de encontrar el objetivo-x se puede reducir a O (N) a O (1).

De esta manera, creamos una tabla hash. Para cada x, primero consultamos si target-x existe en la tabla hash, y luego insertamos x en la tabla hash para asegurarnos de que x no coincida.

Código:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
            if (hashtable.containsKey(target - nums[i])) {
                return new int[]{hashtable.get(target - nums[i]), i};
            }
            hashtable.put(nums[i], i);
        }
        return new int[0];
    }
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_38452841/article/details/109079580
Recomendado
Clasificación