El doble hash es una técnica de programación informática que se utiliza junto con el direccionamiento abierto en tablas hash para resolver colisiones de hash , utilizando un hash secundario de la clave como desplazamiento cuando se produce una colisión. El doble hash con direccionamiento abierto es una estructura de datos clásica en una tabla..
La técnica de doble hash utiliza un valor hash como índice en la tabla y luego avanza repetidamente un intervalo hasta que se localiza el valor deseado, se alcanza una ubicación vacía o se ha explorado toda la tabla; pero este intervalo lo establece una segunda función hash independiente . A diferencia de los métodos alternativos de resolución de colisiones de sondeo lineal y sondeo cuadrático , el intervalo depende de los datos, de modo que los valores que se asignan a la misma ubicación tienen diferentes secuencias de cubetas; esto minimiza las colisiones repetidas y los efectos de la agrupación .
Dadas dos funciones hash aleatorias, uniformes e independientesy, elubicación en la secuencia de cubetas para el valoren una tabla hash decubos es:Las ubicaciones se pueden calcular convenientemente incrementando el hash anterior en, es decir
Generalmente,yse seleccionan de un conjunto de funciones hash universales ;se selecciona para tener una gama deytener una gama deEl doble hash se aproxima a una distribución aleatoria; más precisamente, las funciones hash independientes por pares producen una probabilidad deque cualquier par de claves seguirá la misma secuencia de cubos.
Selección de h 2 (x)
La función hash secundariadebe tener varias características: [ 1 ]
- Nunca debería devolver un índice de cero. Cuando se devuelve 0, solo se examina un índice.
- Tododebería ser relativamente primordial paraDe lo contrario, el número de índices sondeados sobre k elementos sería, que podría ser tan pequeño como 2.
- Debería recorrer toda la tabla.
- Debería ser muy rápido de calcular.
- Debe ser independiente por pares de.
Las características de distribución deson irrelevantes. Es análogo a un generador de números aleatorios.
En la práctica:
- Si se utiliza el hash de división para ambas funciones, los divisores se eligen como números primos.
- Sies una potencia de 2, los dos primeros requisitos generalmente se satisfacen haciendosiempre devuelve un número impar estableciendo el bit menos significativo en 1 (). Esto tiene el efecto secundario de duplicar la probabilidad de colisión debido a un bit desperdiciado. [ 1 ]
Análisis
Supongamos que se seleccionan dos funciones hash.yy se insertanelementos en una tabla hash conranuras. Supongamos que cada inserción de una clavecoloca la llave en la primera ranura disponible de la secuenciadefinido por
Dada esta configuración, los análisis teóricos buscan determinar el tiempo necesario para realizar una inserción adicional (o, equivalentemente, el tiempo necesario para realizar una búsqueda infructuosa). Guibas y Szemerédi [ 2 ] demostraron en 1978 que, si yson uniformemente aleatorios y, entonces el tiempo esperado es. El trabajo posterior de Lueker y Molodowitch [ 3 ] demostró un límite depara cualquiery establecieron que el comportamiento de la tabla hash puede acoplarse directamente al de una solución estándar basada en sondeo aleatorio. Mucho más recientemente, en 2007, Bradford y Katehakis [ 4 ] demostraron que incluso el uso de funciones hash universales , en lugar de funciones totalmente aleatorias, es suficiente para obtener unaatado.
Al igual que otros métodos de direccionamiento abierto, el doble hash se vuelve lineal a medida que la tabla hash se acerca a su capacidad máxima. La heurística habitual consiste en limitar la carga de la tabla al 75 % de su capacidad. Eventualmente, será necesario volver a generar el hash para aumentar su tamaño, como ocurre con todos los demás esquemas de direccionamiento abierto.
Variantes
La tesis doctoral de Peter Dillinger señala que el doble hash produce funciones hash equivalentes no deseadas cuando las funciones hash se tratan como un conjunto, como en los filtros de Bloom : Siy, entoncesy los conjuntos de hashes son idénticos. Esto hace que una colisión sea dos veces más probable que lo esperado.. [ 5 ]
Además, hay un número significativo de conjuntos hash que se superponen en su mayoría; siy, entoncesy comparando valores hash adicionales (ampliando el rango de) no sirve de nada.
Triple hash
Agregar un tercer hash como un término cuadrático ( triple hash ) hace que la superposición sea mucho menos probable, ya que ahora las clases equivalentes deben generarse mediante una colaboración de ambos.y, a un costo de un 50% más de cálculos debido a la función hash añadida. Opciones para el factor para estoincluir[ 6 ] y losnúmeros triangulares. La función hash añadida debe cumplir los mismos requisitos que los enumerados anteriormente para. [ 1 ]
El uso de los números triangulares facilita el cálculo del valor mediante la diferenciación hacia adelante : para elvariedad, [ 1 ]
from collections.abc import Iterator , Callable from typing import TypeVarT = TypeVar ( 'T' ) hashfunc = Callable [ T , int ] # se asume que h1, h2, h3 están definidos y son de tipo hashfuncMÓDULO = ( 1 << 32 )def triple_hash ( key : T , k : int ) -> Iterator [ int ]: """Devuelve k iteraciones de un triple hash.""" x , y , z = h1 ( key ), h2 ( key ), h3 ( key ) yield x for i in range ( 1 , k - 1 ): x = ( x + y ) % MODULUS y = ( y + z ) % MODULUS yield xEste tipo de construcción no elimina por completo los conjuntos equivalentes. Si:
- y
entonces
Doble hash mejorado
Agregar un término cúbico[ 6 ] o(un número tetraédrico ), [ 1 ] sí resuelve el problema, una técnica conocida como doble hash mejorado . El número tetraédrico se puede calcular de manera eficiente mediante diferenciación hacia adelante :
struct key ; /// Opaco /// Reemplace "unsigned int" con otros tipos según sea necesario. (Debe ser unsigned para garantizar el encapsulamiento). typedef unsigned int hashfunc ( struct key const * ); extern hashfunc h1 , h2 ;/// Calcula k valores hash a partir de dos funciones hash subyacentes /// h1() y h2() utilizando doble hash mejorado. Al regresar, /// hashes[i] = h1(x) + i*h2(x) + (i*i*i - i)/6. /// Aprovecha el encapsulamiento automático (reducción modular) /// de los tipos sin signo en C. void ext_dbl_hash ( struct key const * x , unsigned int hashes [], unsigned int n ) { unsigned int a = h1 ( x ), b = h2 ( x ), i = 0 ;hashes [ i ] = a ; para ( i = 1 ; i < n ; i ++ ) { a += b ; // Sumar diferencia cuadrática para obtener cúbica b += i ; // Sumar diferencia lineal para obtener cuadrática // i++ suma diferencia constante para obtener lineal hashes [ i ] = a ; } }Además de rectificar el problema de colisión , el doble hash mejorado también elimina las restricciones numéricas del doble hash enpropiedades de , permitiendo una función hash similar en propiedades a (pero aún independiente de)para ser utilizado. (Utilizando la numeración en § Selección , se eliminan los dos primeros requisitos.) [ 1 ]
Véase también
Referencias
- 1 2 3 4 5 6 Dillinger, Peter C.; Manolios, Panagiotis (15-17 de noviembre de 2004). Filtros de Bloom en la verificación probabilística (PDF) . 5ª Conferencia Internacional sobre Métodos Formales en Diseño Asistido por Computadora (FMCAD 2004). Austin, Texas. CiteSeerX 10.1.1.119.628 . doi : 10.1007/978-3-540-30494-4_26 .
- ↑ Guibas; Szemeredi (1978). "El análisis del doble hash". J. Comput. System Sci . 16 (2): 226– 274. doi : 10.1016/0022-0000(78)90046-6 .
- ↑ Lueker, George; Molodowitch, Mariko (1988). «Análisis más profundo del doble hash». Actas del vigésimo simposio anual de la ACM sobre Teoría de la Computación - STOC '88 . Nueva York, Nueva York, EE. UU.: ACM Press. págs. 354–359 . doi : 10.1145/62212.62246 . ISBN 0-89791-264-0.
- ↑ Bradford, Phillip G.; Katehakis, Michael N. (abril de 2007), "Un estudio probabilístico sobre expansores combinatorios y funciones hash" (PDF) , SIAM Journal on Computing , 37 (1): 83–111 , doi : 10.1137/S009753970444630X , MR 2306284 , archivado del original (PDF) el 25 de enero de 2016 .
- ↑ Dillinger, Peter C. (diciembre de 2010). Almacenamiento de estado aproximado adaptativo (PDF) (tesis doctoral). Northeastern University. págs. 93–112 .
- 1 2 Kirsch, Adam; Mitzenmacher, Michael (septiembre de 2008). "Menos hash, mismo rendimiento: construyendo un mejor filtro de Bloom" (PDF) . Random Structures and Algorithms . 33 (2): 187– 218. CiteSeerX 10.1.1.152.579 . doi : 10.1002/rsa.20208 .
Enlaces externos
- Cómo afecta el almacenamiento en caché al hashing, por Gregory L. Heileman y Wenbin Luo, 2005.
- Animación de tabla hash
- klib es una biblioteca de C que incluye funcionalidad de doble hash.
- Algoritmos de búsqueda
- Hashing