¿Convertir el tamaño de matriz en un número primo ayuda en la implementación de la tabla hash? ¿Por qué?

Marc dio una gran respuesta a esta pregunta, pero quería agregar algunos datos que creo que realmente muestran la importancia de tener una buena función hash y un tamaño de tabla principal.

Estos datos provienen de una conferencia de Jon Bentley para MIT 6.172 (Performance Engineering of Software Systems), durante la cual describió la implementación de una tabla hash para un gran proyecto. La idea aquí es que se nos dan algunos números [matemática] a [/ matemática] y [matemática] c [/ matemática], y queremos dividirlos en algún índice en la tabla hash. Realizó un experimento in vitro en 10 millones de pares ” in vivo” (datos de producción), en varias funciones hash y tamaños de tabla diferentes. Los números en la tabla indican el “costo de búsqueda”, que fue su medida del número de colisiones.

Como puede ver, el tamaño de la tabla es importante para todas las funciones hash probadas, pero es especialmente importante cuando la función hash no es excelente (¡mire los 3 órdenes de aumento de tamaño entre el tamaño de la tabla 8191 a 8192 para las dos primeras funciones hash!)

[matemáticas] \ begin {array} {c | cccccc} \ textbf {Hash function} & \ textbf {8191} & \ textbf {8192} & \ textbf {8209} & \ textbf {9973} & \ textbf {10000} & \ textbf {10007} \\ \ hline a + c & 1.92 & 3510 & 2.06 & 1.69 & 11.5 & 1.77 \\ \ hline a >> 7 + c & 90 y 4196 & 90 y 90 y 102 & 90 \\ \ hline a >> 12 + c & 33 y 189 y 33 y 33 y 47 y 33 \\ \ hline a \ cdot (64 + 8 + 1) + \\ c \ cdot (16 + 4 + 1) y 1.84 y 3510 & 1.92 y 1.83 y 11.5 y 1.79 \\ \ hline a >> 7 \ cdot (64 + 8 + 1) + \\ c \ cdot (16 + 4 + 1) y 1.93 y 27.8 y 1.84 y 1.62 y 11.5 y 1.74 \ \ \ hline a >> 12 \ cdot (64 + 8 + 1) + \\ c \ cdot (16 + 4 + 1) y 1.86 y 2.01 y 1.95 y 1.65 y 1.61 y 1.55 \\ \ end {array} [/ mates]

Fuente: Bentley, Boyle, Krishnan, Meiners – Ingeniería de rendimiento en un sistema heredado – p. dieciséis

Un objetivo clave de la implementación de la tabla hash es minimizar las colisiones, y muchas tablas hash de libros de texto operan evaluando una suma de combinaciones lineales de partes de su módulo de datos n.

Si el número n de ranuras utilizables en la tabla hash es un número primo, se garantiza que cualquier módulo de valor n solo tiene un módulo inverso n, pero esto no se cumple si n no es primo. La existencia de inversas múltiples o la inexistencia de inversas dará como resultado una distribución desigual de sus valores mapeados, porque ya no hay una x única que satisfaga a * x mod n = b, que tiene el efecto de mapear dos valores diferentes módulo n al mismo valor. Esto dará como resultado una mayor probabilidad de colisión.

Puede pensarlo de la siguiente manera, si a tiene dos inversos módulo n, entonces:

ax mod n puede ser igual a ay mod n si x e y son inversas de a. En este caso, tendrá una colisión evitable, ya que x o y habrían encajado en la matriz (ya que son números mod n) pero no colisionaron. Sin embargo, después de la multiplicación por a pueden colisionar. Se garantiza que esto no sucederá si n es primo.

La pregunta es un poco de arenque rojo. El tamaño de la matriz simplemente dicta el módulo aplicado después de la función hash, que simplemente asigna objetos a los enteros. Es el comportamiento de esta función (quizás en relación con el módulo) lo que * realmente * importa. Si tengo 100 elementos que se asignan perfectamente a los números del 1 al 100, entonces no importa mucho si coloco esos elementos en 13 cubos o 14 cubos porque se distribuirán uniformemente de cualquier manera.

Ahora, si su función hash agrupa los datos, entonces el módulo * podría * ayudar dividiendo un grupo en dos secciones, pero eso no tiene nada que ver con la primalidad y todo lo que tiene que ver con dónde están los grupos en relación con su módulo .

Entonces, lo que necesita es una función de hashing que distribuya suficientemente datos arbitrarios sobre un área determinada (creo que probablemente haya un enlace a la entropía de cifrado aquí), no un módulo en particular. Sin embargo, podría estar equivocado y me encantaría ver evidencia de lo contrario.

More Interesting

¿Cuál es el mejor algoritmo?

¿Cómo se puede probar que la ruta única a través de un árbol de expansión mínima entre dos nodos es una ruta más corta de "cuello de botella"?

¿Cuál es una manera de ordenar una matriz en C por una entrada simple?

¿Cuándo es conveniente resolver un problema usando un algoritmo codicioso?

Cómo usar el 'mapa combinatorio' de una triangulación de un polígono 2D para probar si un borde dado de la triangulación es un borde límite

¿Cómo encontraron los pilotos el camino más corto, cuando volaron a larga distancia en 1950?

¿Cuál es la diferencia entre los algoritmos FPgrowth y Apriori en términos de resultados?

¿Cuál es la mejor manera de estudiar la estructura de datos de árbol?

¿Qué hay de malo en mi implementación de tipo de fusión?

¿El aprendizaje automático funciona modificando algoritmos o modificando datos y variables?

¿Cuál es el algoritmo de programación monotónico de velocidad en los sistemas operativos?

¿Vale la pena tomar el curso en línea de comercio algorítmico en Quantinsti?

Dado un conjunto entero tal que cada elemento ocurre 3 veces, excepto un elemento, que ocurre solo una vez, ¿cómo encuentro ese único elemento en el espacio O (1) y en la complejidad del tiempo O (n)?

¿Por qué no podemos ejecutar Bellman Ford desde la fuente y relajar los bordes de los vecinos de forma recursiva y hacer una sola pasada a través de los bordes?

¿Son los gráficos la mejor estructura de datos para representar circuitos? ¿Hay algo mejor?