El hash doble es una técnica de programación informática que se utiliza junto con el direccionamiento abierto en las tablas hash para resolver colisiones de hash , mediante el uso de un hash secundario de la clave como compensación cuando se produce una colisión. El hash doble con direccionamiento abierto es una estructura de datos clásica en una tabla .
La técnica de hash doble utiliza un valor hash como índice en la tabla y luego avanza repetidamente un intervalo hasta que se encuentra el valor deseado, se llega a una ubicación vacía o se ha buscado en 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 contenedores; esto minimiza las colisiones repetidas y los efectos de la agrupación .
Dadas dos funciones hash aleatorias, uniformes e independientes y , la ubicación n en la secuencia de cubos para el valor en una tabla hash de cubos es:
Generalmente, y se seleccionan de un conjunto de funciones hash universales ; se selecciona para que tengan un rango de y para que tengan un rango de . El hash doble se aproxima a una distribución aleatoria; más precisamente, las funciones hash independientes por pares producen una probabilidad de que cualquier par de claves siga la misma secuencia de cubos.
Selección de h2(k)
La función hash secundaria debe tener varias características:
- Nunca debería producir un índice de cero.
- Debería recorrer toda la tabla.
- Debería ser muy rápido de calcular.
- Debería ser independiente por pares de .
- Las características de distribución de son irrelevantes. Es análogo a un generador de números aleatorios.
- Todos deben ser primos entre sí respecto a | T |.
En la práctica:
- Si se utiliza el algoritmo de división para ambas funciones, los divisores se eligen como primos.
- Si | T | es una potencia de 2, el primer y el último requisito se satisfacen normalmente haciendo que siempre se devuelva un número impar. Esto tiene el efecto secundario de duplicar la probabilidad de colisión debido a un bit desperdiciado. [1]
Análisis
Sea el número de elementos almacenados en , entonces el factor de carga de es . Es decir, comience seleccionando aleatoriamente, de manera uniforme e independiente dos funciones hash universales y construya una tabla hash doble . Todos los elementos se colocan mediante hash doble utilizando y . Dada una clave , la ubicación hash -st se calcula mediante:
Supongamos que el factor de carga es fijo . Bradford y Katehakis [2]
demostraron que el número esperado de sondeos para una búsqueda fallida en , aún utilizando estas funciones hash elegidas inicialmente, es independientemente de la distribución de las entradas. La independencia por pares de las funciones hash es suficiente.
Al igual que todas las demás formas de direccionamiento abierto, el hash doble se vuelve lineal a medida que la tabla hash se acerca a su capacidad máxima. La heurística habitual es limitar la carga de la tabla al 75 % de su capacidad. Con el tiempo, será necesario volver a aplicar el hash a un tamaño mayor, como ocurre con todos los demás esquemas de direccionamiento abierto.
Variantes
La tesis doctoral de Peter Dillinger [3] señala que el hash doble produce funciones hash equivalentes no deseadas cuando las funciones hash se tratan como un conjunto, como en los filtros Bloom : si y , entonces y los conjuntos de hashes son idénticos. Esto hace que una colisión sea dos veces más probable que la esperada .
Además, hay una cantidad significativa de conjuntos hash que en su mayoría se superponen; si y , entonces , y comparar valores hash adicionales (expandiendo el rango de ) no es de ayuda.
Triple hash
Agregar un término cuadrático [4] (un número triangular ) o incluso ( triple hash ) [5] a la función hash mejora un poco la función hash [4] pero no soluciona este problema; si:
- y
entonces
Hashing doble mejorado
La suma de un término cúbico [4] o (un número tetraédrico ), [1] resuelve el problema, una técnica conocida como hash doble mejorado . Esto se puede calcular de manera eficiente mediante la diferenciación hacia adelante :
struct key ; /// Opaco /// Utilice otros tipos de datos cuando sea necesario. (Debe estar sin signo para garantizar el ajuste). extern unsigned int h1 ( struct key const * ), h2 ( struct key const * ); /// Calcula k valores hash a partir de dos funciones hash subyacentes /// h1() y h2() usando hash doble mejorado. Al regresar, /// hashes[i] = h1(x) + i*h2(x) + (i*i*i - i)/6. /// Aprovecha el encapsulado automático (reducción modular) /// de 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 ; hashes [ i ] = a ; for ( i = 1 ; i < n ; i ++ ) { a += b ; // Agrega diferencia cuadrática para obtener cúbica b += i ; // Agrega diferencia lineal para obtener cuadrática // i++ agrega diferencia constante para obtener lineal hashes [ i ] = a ; } }
Además de corregir el problema de colisión, el doble hash mejorado también elimina las restricciones numéricas del doble hash en las propiedades de , lo que permite utilizar una función hash similar en propiedades a (pero aún independiente de). [1]
Véase también
Referencias
- ^ abc Dillinger, Peter C.; Manolios, Panagiotis (15-17 de noviembre de 2004). Filtros Bloom en verificación probabilística (PDF) . Conferencia internacional de 5 h 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.
- ^ Bradford, Phillip G.; Katehakis, Michael N. (abril de 2007), "Un estudio probabilístico sobre expansores combinatorios y hash" (PDF) , SIAM Journal on Computing , 37 (1): 83–111, doi :10.1137/S009753970444630X, MR 2306284, archivado desde el 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.
- ^ abc Kirsch, Adam; Mitzenmacher, Michael (septiembre de 2008). "Menos hash, mismo rendimiento: creación de un mejor filtro Bloom" (PDF) . Estructuras y algoritmos aleatorios . 33 (2): 187–218. CiteSeerX 10.1.1.152.579 . doi :10.1002/rsa.20208.
- ^ Alternativamente definido con el número triangular, como en Dillinger 2004.
Enlaces externos
- Cómo afecta el almacenamiento en caché al hash por Gregory L. Heileman y Wenbin Luo 2005.
- Animación de tabla hash
- klib es una biblioteca C que incluye funcionalidad de doble hash.