¿Por qué es mejor usar un número primo como mod en una función hash?

58

Si tengo una lista de valores clave del 1 al 100 y quiero organizarlos en una matriz de 11 cubos, me han enseñado a formar una función mod

H=kmod 11

Ahora todos los valores se colocarán uno tras otro en 9 filas. Por ejemplo, en el primer depósito habrá 0,11,22 . En el segundo, habrá 1,12,23 etc.

Digamos que decidí ser un chico malo y usar un no primo como mi función de hashing: toma 12. Uso de la función Hashing

H=kmod 12

daría como resultado una tabla hash con valores 0,12,24 en el primer depósito, 1,13,25 etc. en el segundo y así sucesivamente.

Esencialmente son lo mismo. No reduje las colisiones y no extendí las cosas mejor usando el código hash del número primo y no puedo ver cómo es beneficioso.

CodyBugstein
fuente
Pregunta relevante, por qué usamos xor en la función hash stackoverflow.com/questions/5889238/…
shuva

Respuestas:

63

Considere el conjunto de claves y una tabla hash donde el número de cubos es . Dado que es un factor de , las claves que son múltiplos de se dividirán en cubos que son múltiplos de :K={0,1,...,100}m=1231233

  • Las teclas se cifrarán en el depósito .{0,12,24,36,...}0
  • Las teclas se encapsularán al cubo .{3,15,27,39,...}3
  • Las teclas se encapsularán al cubo .{6,18,30,42,...}6
  • Las teclas se encapsularán al cubo .{9,21,33,45,...}9

Si está distribuido uniformemente (es decir, cada clave en es igualmente probable que ocurra), entonces la elección de no es tan crítica. Pero, ¿qué sucede si no está distribuido uniformemente? Imagine que las claves que tienen más probabilidades de ocurrir son los múltiplos de . En este caso, todos los cubos que no son múltiplos de estarán vacíos con alta probabilidad (lo cual es realmente malo en términos de rendimiento de la tabla hash).KKmK33

Esta situación es más común de lo que parece. Imagine, por ejemplo, que realiza un seguimiento de los objetos en función de dónde están almacenados en la memoria. Si el tamaño de palabra de su computadora es de cuatro bytes, entonces tendrá claves hash que son múltiplos de . No hace falta decir que elegir como múltiplo de sería una elección terrible: tendría cubos completamente vacíos y todas sus llaves colisionarían en los cubos restantes .4m43m/4m/4

En general:

Cada clave en que comparte un factor común con el número de cubos se convertirá en un cubo que es un múltiplo de este factor.Km

Por lo tanto, para reducir al mínimo las colisiones, es importante para reducir el número de factores comunes entre y los elementos de . ¿Cómo se puede lograr esto? Al elegir como un número que tiene muy pocos factores: un número primo .mKm

Mario Cervera
fuente
Acabo de ver que mi consulta está alineada con su respuesta. ¿Crees que la función hash en mi consulta es válida?
intercambio excesivo el
@overexchange: respondí a tu pregunta. Esta respuesta también puede ser de su interés.
Mario Cervera
¿por qué es que la elección de m solo importa si K está sesgada? ¿No es cierto que tendremos un rendimiento peor con m malo incluso si K está distribuido uniformemente?
vorou
Depende de lo que quieras decir con "mala ". Si quiere decir "pequeño en comparación con el número de elementos en la tabla hash" (es decir, alto factor de carga ), entonces, el rendimiento será pobre. Sin embargo, si quiere decir "no primo", este hecho no es tan importante si todas las claves son igualmente probables porque se distribuirán uniformemente en la tabla hash. La pregunta en sí misma proporciona un ejemplo. m
Mario Cervera
16

Si una colisión es menos probable usando primos depende de la distribución de sus claves.

Si muchas de sus teclas tienen la forma y su función hash es , entonces estas teclas van a un pequeño subconjunto de los cubos si f divide . Por lo tanto, debe minimizar el número de tales , que puede lograrse eligiendo un primo.a+kbH(n)=nmodmbnb

Si, por otro lado, desea tener de a cubos y sabe que las diferencias que son múltiplos de son más probables que las diferencias que son múltiplos de y , puede elegir para su aplicación muy especial.1112112312

frafl
fuente
1
Pero si mis claves no tienen la forma entonces ¿ no importa? ¿Está bien? a+k×bm
CodyBugstein
1
@lmray, si sus claves están distribuidas uniformemente, no importa. Si no lo están, dependerá de la distribución de precisión para que importe o no. mm
Programador
Acabo de revertir la última edición, olvidé que . 12>11
frafl
3
¿Quiso decir que "vaya a un pequeño subconjunto de los cubos si f divide "? bm
Mikhail Dubov
8

Si esto tiene un impacto (también) depende de cómo trate las colisiones. Cuando se usan algunas variantes de hashing abierto , el uso de primos garantiza que se encuentren ranuras vacías siempre que la tabla esté suficientemente vacía.

Intente mostrar lo siguiente, por ejemplo:

Supongamos que queremos insertar un elemento que los hashes para hacer frente a y las colisiones a resolver por las posiciones que tratan , posteriormente, para .aa+i2i=1,2,

Muestre que este procedimiento siempre produce una posición vacía si la tabla hash es del tamaño , un primo mayor que , y al menos la mitad de todas las posiciones están libres.pp3

Sugerencia: Utilice el hecho de que el módulo de anillo de clase de residuo es un campo si es primo y, por lo tanto, tiene como máximo soluciones.ppi2=c2

Rafael
fuente
2

Si su función hash es de la forma donde es primo y se elige al azar, entonces la probabilidad de que 2 claves distintas de hash para el mismo segmento sea . Entonces, para , que es muy pequeño.h(k)=a×kmodmma1mm=1009Pr{h(x)=h(y),xy}=0.00099108027

Este esquema se conoce como: Hashing Universal.

saadtaame
fuente