2011-02-07 15 views
5

Recientemente me han entrenado en un par de entrevistas sobre Hashtables y cuándo es necesario anular el GetHashCode(). La discusión siguió profundizándose hasta que tiré la toalla.Preguntas de la entrevista relacionadas con Hashtable y el diccionario

Ahora estoy haciendo una investigación para cubrir todo para estar listo para la próxima vez.

He encontrado este excelente artículo que me gustaría compartir: http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx#datastructures20_2_topic5

1) Algo que no me siento muy cómodo con * son el hecho de que los diccionarios se basan Hash, pero las listas no son aparentemente . ¿Eso solo significa que la búsqueda en una lista <> y matriz [] es lineal, mientras que la búsqueda en un diccionario o hashtable es constante y, por lo tanto, mucho más rápida? ¿Esto es todo?

2) Si utilizo una clase como clave en un diccionario, debo anular GetHashcode() en esa clase en función de los campos de identificación necesarios para que las instancias sean únicas. Sin embargo, todavía podría suceder que ambos campos ID sean iguales y se genere el mismo código hash. Si este es el caso, ¿qué sucede durante una colisión de las dos instancias con el mismo código hash?

3) ¿Cómo se puede resolver la colisión? Leí en el artículo sobre la metodología de reajuste en caso de colisión para Hashtable y encadenamiento para el diccionario. Pero todavía no estoy seguro de cómo funciona exactamente, ya que no soy un genio de las matemáticas. : - \ ¿Alguien puede explicar mejor cómo funciona?

Muchas gracias, Kave

+2

Si se genera el mismo código hash la función igual se ejecuta en el objeto para determinar la igualdad. Por lo tanto, no se olvide de anular esa función también. – Magnus

+0

Solo quería agradecer a todos los que contribuyeron. Tuve una entrevista y me pidieron HashSet lol. De una sola vez, le di todos los pro/contras de hash como discutimos y quedó impresionado. Pasó la entrevista. Entonces debe ser correcto. ;) – Houman

Respuesta

4

1) En general, sí, un Dictionary<T> o HashSet<T> tiene acceso de tiempo constante. La ubicación de un elemento en un List<T> no ordenado o matriz se debe hacer de forma lineal. Las colecciones ordenadas le permiten realizar búsquedas binarias, otorgando a O (log n) el tiempo de acceso.

2) Si anula GetHashCode en .NET, también debe anular el método Equals. En .NET Dictionary y HashSet, no puede insertar elementos que sean iguales. Las colisiones hash son inevitables en el caso general (a menos que haya calculado un hash perfecto). Hay varias formas de resolver colisiones.

3) Para obtener más información sobre la resolución de colisiones, consulte http://en.wikipedia.org/wiki/Hash_table.

+0

particularmente en las colisiones de .net se resuelven al tener lista vinculada unida al cubo – Andrey

+0

Muchas gracias por su respuesta. Más abajo escribí un comentario a la respuesta de Steven, que también podría serle preguntado. :) Como mencionaste el hash perfecto, ¿lo conseguiría usando una clave primaria 100% exclusiva de DB? ¿Y la colisión hash cae bajo la responsabilidad de los desarrolladores o de todos modos se está cuidando automáticamente? – Houman

+1

Imagine que tiene 1,000 claves únicas en su base de datos y su tabla hash puede contener cualquiera de esas 100 claves. El código hash que cree se correlacionará con la tabla hash en una de esas 100 ranuras. Entonces, incluso si sus códigos hash son únicos, puede tener colisiones en la tabla hash. La función de hash mínimamente perfecta solo funciona cuando hay una asignación uno a uno de los códigos hash a las ranuras en la tabla hash. Es responsabilidad del desarrollador definir una función hash que proporcione una distribución razonablemente uniforme, pero la resolución de colisiones es responsabilidad de la implementación de la tabla hash. –

1

Una tabla hash es una estructura de datos. Se puede encontrar más información en when looking for more general information.

1) Una búsqueda predeterminada en las listas es lineal (todos los elementos deben atravesarse). El hashing perfecto (sin colisiones) permite búsquedas de tiempo constante en el peor de los casos. Más colisiones resultan en una búsqueda más lenta.

2) Las colisiones hash son prácticamente inevitables cuando se crea un subconjunto aleatorio de un gran conjunto de claves posibles. Por lo tanto, la mayoría de las implementaciones de tablas hash tienen alguna estrategia de resolución de colisiones para manejar dichos eventos. La implementación Hashtable de .NET parece usar double hashing.

3) Esto es algo que no debes preocuparte, siempre y cuando proporciones los códigos hash adecuados. Cuando esté interesado, lea el artículo de la wiki sobre tablas hash, que explica varias técnicas.

ACTUALIZACIÓN: Hay a difference en la implementación de Hashtable y diccionarios en el manejo de colisiones. Aparentemente, Hashtable es obsoleto y se prefiere Dictionary o HashSet.

Como Jim Mischel menciona, debe anular GetHashCode y Equals. No es posible insertar elementos que son iguales, pero los elementos con el mismo código hash son manejados por el tipo de colección que elijas.

+0

Muchas gracias por su respuesta. De manera realista, si baso mi GetHashCode() en un campo de clave principal recuperado de DB, ¿no llevaré los cambios de una colisión a cero? Pero en caso de que el hash pueda duplicarse después de todo, ¿no es .NET el que se encarga de volver a procesar/duplicar los valores en caso de una colisión de forma automática? En la entrevista, sonó como si fuera mi responsabilidad hacer algo al respecto yo mismo. :) Tal vez solo querían saber sobre el doble hash que se usa internamente, lo cual no dije. – Houman

+1

Si el tipo DB pk es int y el diccionario solo contiene objetos de ese tipo que sí. (Simplemente devolverá el campo pk en la función GetHAshCode). Pero la mayoría de las veces necesita una buena función de hashing, consulte http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/3880895# 3880895 – Magnus

+0

Estoy de acuerdo con @Magnus. En cuanto a las colisiones, es algo de lo que debe tenerse en cuenta para que comprenda por qué es importante una función hashing única y única. –

Cuestiones relacionadas