¿De las respuestas a (Cuándo) es la búsqueda de tabla hash O (1)? , Deduzco que las tablas hash tienen comportamiento en el peor de los casos, al menos amortizado, cuando los datos satisfacen ciertas condiciones estadísticas, y existen técnicas para ayudar a ampliar estas condiciones.
Sin embargo, desde la perspectiva de un programador, no sé de antemano cuáles serán mis datos: a menudo provienen de alguna fuente externa. Y rara vez tengo todos los datos a la vez: a menudo las inserciones y eliminaciones ocurren a una velocidad que no está muy por debajo de la velocidad de las búsquedas, por lo que el procesamiento previo de los datos para ajustar la función hash está desactivado.
Entonces, dando un paso: dado algunos conocimientos sobre la fuente de datos, ¿cómo puedo determinar si una tabla hash tiene la posibilidad de tener operaciones , y posiblemente qué técnicas usar en mi función hash?
fuente
Respuestas:
Existen varias técnicas que garantizan que las búsquedas siempre requerirán operaciones O (1), incluso en el peor de los casos.
El peor de los casos ocurre cuando un atacante malintencionado (Mallory) le proporciona deliberadamente datos que Mallory ha seleccionado específicamente para hacer que el sistema funcione lentamente.
Una vez que haya elegido alguna función hash en particular, probablemente sea demasiado optimista suponer que Mallory nunca descubrirá qué función hash eligió. Una vez que Mallory descubre qué función hash seleccionó, si permite que Mallory le proporcione una gran cantidad de datos para insertar en su tabla hash utilizando esa función hash, entonces está condenado: Mallory puede generar internamente rápidamente miles de millones de elementos de datos, hágalos con su Función hash para encontrar qué elementos de datos pueden colisionar, y luego alimentarlo con millones de uno en mil elementos de datos que probablemente colisionen, lo que lleva a búsquedas que se ejecutan mucho más lentamente que O (1).
Todas las técnicas que garantizan "búsquedas de O (1) incluso en el peor de los casos" evitan este problema haciendo un poco de trabajo adicional en cada inserción para garantizar que, en el futuro, cada búsqueda posible pueda tener éxito en el tiempo de O (1) . En particular, suponemos (en el peor de los casos) que Mallory tarde o temprano descubrirá qué función hash estamos utilizando; pero solo tiene la oportunidad de insertar algunos elementos de datos antes de elegir una función hash diferente ( hashing de tabulación u otro hashing universal ) que seleccionamos especialmente para que todos los datos que tenemos hasta ahora se puedan buscar en 2 o 3 sondas, es decir, O (1). Debido a que seleccionamos al azar esta función, podemos estar bastante seguros de que Mallory no sabrá qué función elegimos por un tiempo. Incluso si MalloryInmediatamente nos da datos que, incluso con esta nueva función hash, colisiona con datos anteriores, luego podemos elegir otra función hash nueva y nueva, de modo que, después de volver a escribir, todos los datos anteriores que él y todos los demás nos hayan alimentado ahora se puedan ver arriba en 2 o 3 sondas en el peor de los casos, es decir, búsquedas de O (1) en el peor de los casos.
Es bastante fácil seleccionar aleatoriamente una nueva función hash y volver a mostrar la tabla completa con la frecuencia suficiente para garantizar que cada búsqueda sea siempre O (1). Si bien esto garantiza que cada búsqueda sea siempre O (1), estas técnicas, al insertar el enésimo elemento en una tabla hash que ya contiene elementos N-1, ocasionalmente pueden requerir tiempo O (N) para ese inserto. Sin embargo, es posible diseñar el sistema de manera que, incluso cuando Mallory le brinde deliberadamente nuevos datos que, utilizando la nueva función hash, colisionen con datos anteriores, el sistema puede aceptar muchos elementos de Mallory y otros antes de que necesite hacer un reconstrucción completa de O (N). Las técnicas de tabla hash que seleccionan una nueva función y repiten para garantizar las búsquedas de O (1), incluso en el peor de los casos, incluyen:
Estructuras de datos / Tablas hash
fuente
fuente
En el pasado, de acuerdo con un documento de Usenix de Crosby y Wallach , los lenguajes de programación comunes no hacían nada como esto, dejando muchas aplicaciones web (y otros servidores) abiertas a un ataque DoS basado en colisiones de fabricación. (El documento es de 2003, pero sugiere que Dan Bernstein había descubierto la misma idea bastante antes).
Una búsqueda rápida en Google proporciona afirmaciones de que el estado del arte en términos de implementaciones ha mejorado y no ha mejorado .
Otra cosa aparte es que en un mundo de gran ancho de banda, los ataques de tiempo hacen que no sea tan difícil encontrar colisiones en línea (en oposición a fuera de línea como sugiere el enlace Crosby-Wallach). Me parece recordar que Daniel Golovin tuvo resultados hace algunos años en estructuras de datos que no son vulnerables a los ataques de tiempo, pero no sé si se usan ampliamente.
fuente
El análisis de casos promedio para las tablas hash se realiza bajo el supuesto habitual de uniformidad de las entradas, lo que una vez se debe a la maquinilla de afeitar de occam.
Si tiene conocimiento adicional sobre el dominio y la distribución de las claves, puede tomar el mismo análisis de caso promedio y reemplazar la distribución uniforme con su distribución y recalcular las expectativas, al menos en teoría.
Por supuesto, la dificultad radica en el hecho de que el análisis no uniforme de casos de avaerage es difícil de hacer. Y su "conocimiento" puede no ser convenientemente expresable como una distribución que pueda usarse fácilmente en dicho análisis.
Obviamente, lo más fácil de hacer son las simulaciones. Implemente las tablas hash y observe cómo funcionan para su conjunto típico de entradas.
fuente
fuente