¿Para qué tipo de datos son las operaciones de tabla hash O (1)?

18

¿De las respuestas a (Cuándo) es la búsqueda de tabla hash O (1)? , Deduzco que las tablas hash tienen O(1) 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 O(1) , y posiblemente qué técnicas usar en mi función hash?

Gilles 'SO- deja de ser malvado'
fuente
Ah, y las tablas hash versus los árboles binarios están relacionadas, pero aquí me estoy centrando en las tablas hash y cuándo están (o no) en su mejor momento.
Gilles 'SO- deja de ser malvado'
El mejor caso para cualquier función hash es cuando los datos se distribuyen uniformemente.
0x0
@Sunil: No es cierto. Puede tener funciones hash personalizadas.
Raphael
Creo que esta pregunta es demasiado amplia. En particular, ¿puede concretar cómo sería el conocimiento sobre las fuentes de datos?
Raphael
@Raphael Por ejemplo, si las claves son cadenas: nombres de personas, nombres de archivos en un directorio, etiquetas XML, hashes de archivos, ...
Gilles 'SO- deja de ser malvado'

Respuestas:

4

Existen varias técnicas que garantizan que las búsquedas siempre requerirán operaciones O (1), incluso en el peor de los casos.

¿Cómo puedo determinar si una tabla hash tiene la posibilidad de tener operaciones O (1) y posiblemente qué técnicas usar en mi función hash?

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:

  • cuckoo hashing garantiza que cada búsqueda de clave tenga éxito con un máximo de 2 cálculos de hash y 2 búsquedas de tabla.
  • El hash de rayuela garantiza que cada búsqueda de clave tenga éxito después de inspeccionar un número pequeño de entradas consecutivas H (quizás H = 32) en la tabla.
  • hashing dinámico perfecto : el artículo de 1994 de Dietzfelbinger es el primero que he leído que señala que, a pesar de que se repite "con frecuencia" para garantizar que cada búsqueda clave siempre tenga éxito con 2 cálculos hash y 2 búsquedas, es posible hacer una repetición completa tan raramente que, a pesar de que cada repetición completa utiliza el tiempo O (n), el costo promedio esperado de las inserciones y eliminaciones se amortiza O (1).

Estructuras de datos / Tablas hash

David Cary
fuente
5

O(1)

O(1)O(norte2W)

O(Iniciar sesiónnorte/ /Iniciar sesiónIniciar sesiónnorte)O(1)

A
fuente
5

hun,si(X)=unX+simodificaciónpag miembro de la familia , donde el adversario no conoce de antemano la elección aleatoria . Esto es similar a cómo se analizan los algoritmos aleatorios también: la expectativa se toma sobre las elecciones del algoritmo, no la distribución de entrada.

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.

Louis
fuente
0

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.

uli
fuente
8
Tengo que estar en desacuerdo con la primera oración. La suposición estándar es que la función hash es aleatoria, no los datos de entrada. Suponiendo que los datos distribuidos uniformemente empujan el análisis al reino de la fantasía, ¡los datos del mundo real nunca son uniformes! Pero existen técnicas de libros de texto para hacer que las funciones hash sean lo suficientemente uniformes. Ver hashing universal y específicamente hashing de tabulación .
JeffE
@JeffE Mira el análisis de caso promedio en la respuesta de Raphael, él afirma esta suposición de uniformidad. No puede hacer un análisis de caso promedio sin una distribución. Tienes que elegir uno y si no se da, la navaja de Occam sugiere el uniforme.
uli
66
Por supuesto que tienes una distribución; es la distribución que usa para elegir la función hash. Elegir una distribución para los datos de entrada es como buscar las claves perdidas debajo de la farola; claro, la luz es mejor, pero probablemente no es donde los dejaste caer.
JeffE
@JeffE Así es como se realiza un análisis de caso promedio, elige una distribución y comienza a calcular. Como siempre, la elección de la distribución es discutible. Le invitamos a hacer un análisis de caso promedio no uniforme.
uli
44
Sí, sé cómo se hace. (Verifique mi perfil). Si desea que su análisis sea predictivo (que es el punto de análisis completo), debe aleatorizar la función hash. Entonces sabes la distribución precisa, porque la elegiste.
JeffE
-1

nortenorte!

isturdy
fuente