¿Por qué Python usa la tabla hash para implementar dict, pero no Red-Black Tree?
Cual es la clave ¿Actuación?
python
data-structures
longdeqidao
fuente
fuente
Respuestas:
Esta es una respuesta general, no específica de Python.
Comparación de complejidad algorítmica
El problema con las tablas hash es que los hash pueden colisionar. Existen varios mecanismos para resolver colisiones, por ejemplo, direccionamiento abierto o encadenamiento separado. El peor de los casos es que todas las claves tienen el mismo código hash, en cuyo caso una tabla hash se degradará en una lista vinculada.
En todos los demás casos, una tabla hash es una gran estructura de datos que es fácil de implementar y ofrece un buen rendimiento. Una desventaja es que las implementaciones que pueden hacer crecer rápidamente la tabla y redistribuir sus entradas probablemente desperdiciarán casi tanta memoria como la que realmente se está utilizando.
Los árboles RB se autoequilibran y no cambian su complejidad algorítmica en el peor de los casos. Sin embargo, son más difíciles de implementar. Sus complejidades promedio también son peores que las de una tabla hash.
Restricciones sobre llaves
Todas las claves en una tabla hash deben ser hashables y comparables para la igualdad entre ellas. Esto es especialmente fácil para cadenas o enteros, pero también es bastante sencillo de extender a tipos definidos por el usuario. En algunos lenguajes como Java, estas propiedades están garantizadas por definición.
Las claves en un árbol RB deben tener un orden total: cada clave debe ser comparable con cualquier otra clave, y las dos claves deben ser más pequeñas, mayores o iguales. Esta igualdad de orden debe ser equivalente a la igualdad semántica. Esto es sencillo para los números enteros y otros números, también es bastante fácil para las cadenas (el orden solo necesita ser consistente y no observable externamente, por lo que el orden no necesita considerar las configuraciones regionales [1] ), pero es difícil para otros tipos que no tienen un orden inherente . Es absolutamente imposible tener claves de diferentes tipos a menos que sea posible alguna comparación entre ellas.
[1]: En realidad, estoy equivocado aquí. Es posible que dos cadenas no sean iguales en bytes, pero aún así sean equivalentes según las reglas de algún idioma. Vea, por ejemplo, normalizaciones Unicode para un ejemplo en el que dos cadenas iguales se codifican de manera diferente. Si la composición de caracteres Unicode es importante para su clave hash es algo que la implementación de una tabla hash no puede saber.
Uno podría pensar que una solución barata para las claves de RB-Tree sería probar primero la igualdad, luego comparar la identidad (es decir, comparar punteros). Sin embargo, este orden no sería transitivo: si
a == b
yid(a) > id(c)
, entonces debe seguir esoid(b) > id(c)
también, lo cual no está garantizado aquí. Entonces, en su lugar, podríamos usar el código hash de claves como claves de búsqueda. Aquí, el orden funciona correctamente, pero podríamos terminar con varias claves distintas con el mismo código hash, que se asignarán al mismo nodo en el árbol RB. Para resolver estas colisiones hash, podemos usar el encadenamiento separado al igual que con las tablas hash, pero esto también hereda el peor comportamiento de las tablas hash, el peor de ambos mundos.Otros aspectos
Espero que una tabla hash tenga una mejor localidad de memoria que un árbol, porque una tabla hash es esencialmente solo una matriz.
Las entradas en ambas estructuras de datos tienen una sobrecarga bastante alta:
Las inserciones y eliminaciones en un árbol RB implican rotaciones de árbol. Estos no son realmente costosos, pero implican una sobrecarga. En un hash, la inserción y eliminación no son más caras que un simple acceso (aunque cambiar el tamaño de una tabla hash tras la inserción es un
O(n)
esfuerzo).Las tablas hash son inherentemente mutables, mientras que un árbol RB también podría implementarse de manera inmutable. Sin embargo, esto rara vez es útil.
fuente
Hay toda una serie de razones que pueden ser ciertas, pero es probable que las principales sean:
¿Es más fácil de escribir / mantener y un ganador de rendimiento en casos de uso típicos? ¡Inscríbeme, por favor!
fuente