Entonces, si tengo que elegir entre una tabla hash o un árbol de prefijos, ¿cuáles son los factores discriminantes que me llevarían a elegir uno sobre el otro? Desde mi punto de vista ingenuo, parece que usar un trie tiene algo de sobrecarga adicional ya que no está almacenado como una matriz, pero que en términos de tiempo de ejecución (suponiendo que la clave más larga es la palabra inglesa más larga) puede ser esencialmente O (1) (en relación con el límite superior). ¿Quizás la palabra inglesa más larga tiene 50 caracteres?
Las tablas hash son de búsqueda instantánea una vez que obtiene el índice . Sin embargo, tener la clave para obtener el índice parece que podría tomar fácilmente cerca de 50 pasos.
¿Alguien puede proporcionarme una perspectiva más experimentada sobre esto? ¡Gracias!
fuente
00110010
podría ser el byte de entrada, pero desea incluir la coincidencia00111010
que solo se elimina un bit.Respuestas:
Ventajas de los intentos:
Los basicos:
Nuevas operaciones:
Ventajas de la estructura vinculada:
Ventajas de las tablas hash:
fuente
Todo depende de qué problema estés tratando de resolver. Si todo lo que necesita hacer es inserciones y búsquedas, vaya con una tabla hash. Si necesita resolver problemas más complejos, como consultas relacionadas con prefijos, entonces un trie podría ser la mejor solución.
fuente
Todo el mundo conoce la tabla hash y sus usos, pero no es exactamente un tiempo de búsqueda constante, depende de qué tan grande sea la tabla hash, la complejidad computacional de la función hash.
Crear enormes tablas hash para una búsqueda eficiente no es una solución elegante en la mayoría de los escenarios industriales en los que incluso la latencia / escalabilidad pequeñas son importantes (p. Ej., Comercio de alta frecuencia). Debe preocuparse por las estructuras de datos que se optimizarán para el espacio que ocupa en la memoria también para reducir la pérdida de caché.
Un muy buen ejemplo donde trie se adapta mejor a los requisitos es el middleware de mensajería. Tiene un millón de suscriptores y editores de mensajes en varias categorías (en términos de JMS: temas o intercambios); en tales casos, si desea filtrar mensajes basados en temas (que en realidad son cadenas), definitivamente no desea crear una tabla hash para el millón de suscripciones con millones de temas. Un mejor enfoque es almacenar los temas en trie, por lo que cuando el filtrado se realiza en función de la coincidencia de temas, su complejidad es independiente del número de temas / suscripciones / editores (solo depende de la longitud de la cadena). Me gusta porque puedes ser creativo con esta estructura de datos para optimizar los requisitos de espacio y, por lo tanto, tener una menor pérdida de caché.
fuente
Usa un árbol:
fuente
Hay algo que no he visto a nadie mencionar explícitamente que creo que es importante tener en cuenta. Tanto las tablas hash como los intentos de varios tipos suelen tener
O(k)
operaciones, dondek
es la longitud de la cadena en bits (o equivalente en caracteres).Esto supone que tiene una buena función hash. Si no desea que "granja" y "animales de granja" hagan hash con el mismo valor, entonces la función hash tendrá que usar todos los bits de la clave, por lo que el hash "animales de granja" debería tomar aproximadamente el doble de tiempo "farm" (a menos que esté en algún tipo de escenario de hash rodante, pero también hay escenarios de ahorro de operación algo similares con intentos). Y con un trie de vainilla, está claro por qué insertar "animales de granja" tomará aproximadamente el doble de tiempo que solo "granja". A la larga, también es cierto con los intentos comprimidos.
fuente
La inserción y búsqueda en un trie es lineal con la longitud de la cadena de entrada O (s).
Un hash le dará un O (1) para búsqueda e inserción, pero primero debe calcular el hash en función de la cadena de entrada que nuevamente es O (s).
Conclusión, la complejidad del tiempo asintótico es lineal en ambos casos.
El trie tiene algo más de gastos generales desde la perspectiva de los datos, pero puede elegir un trie comprimido que lo pondrá de nuevo, más o menos en un empate con la tabla hash.
Para romper el empate, hágase esta pregunta: ¿Necesito buscar solo palabras completas? ¿O debo devolver todas las palabras que coinciden con un prefijo? (Como en un sistema de ingreso de texto predictivo). Para el primer caso, ve por un hash. Es un código más simple y limpio. Más fácil de probar y mantener. Para un caso de uso más elaborado en el que los prefijos o sufijos importan, elija un trie.
Y si lo haces solo por diversión, la implementación de un trie daría un buen uso a un domingo por la tarde.
fuente
La implementación de HashTable ahorra espacio en comparación con la implementación básica de Trie . Pero con las cadenas, el orden es necesario en la mayoría de las aplicaciones prácticas. Pero HashTable perturba totalmente el orden lexográfico. Ahora, si su aplicación está realizando operaciones basadas en el orden lexográfico (como búsqueda parcial, todas las cadenas con el prefijo dado, todas las palabras en orden ordenado), debe usar Intentos. Para solo buscar, se debe usar HashTable (ya que podría decirse que proporciona un tiempo de búsqueda mínimo).
PD: Aparte de estos, los árboles de búsqueda ternarios (TST) serían una excelente opción. Su tiempo de búsqueda es más que HashTable, pero es eficiente en todas las demás operaciones. Además, es más eficiente en espacio que los intentos.
fuente
Algunas aplicaciones (generalmente integradas, en tiempo real) requieren que el tiempo de procesamiento sea independiente de los datos. En ese caso, una tabla hash puede garantizar un tiempo de ejecución conocido, mientras que un trie varía según los datos.
fuente