Articulo de referencia

Trie mapeado a matriz hash

Un trie mapeado a matriz hash [ 1 ] ( HAMT , / ˈ h æ m t / ) es una implementación de una matriz asociativa que combina las características de una tabla hash y un trie mapeado a...

Un trie mapeado a matriz hash [ 1 ] ( HAMT , / ˈ h æ m t / ) es una implementación de una matriz asociativa que combina las características de una tabla hash y un trie mapeado a matriz . [ 1 ] Es una versión refinada de la noción más general de un árbol hash .

Operación

Un HAMT es un trie mapeado a una matriz donde las claves se someten primero a una función hash para garantizar una distribución uniforme de las claves y una longitud de clave constante.

En una implementación típica del trie mapeado por matriz de HAMT, cada nodo contiene una tabla con un número fijo N de ranuras, donde cada ranura contiene un puntero nulo o un puntero a otro nodo. N suele ser 32. Dado que asignar espacio para N punteros en cada nodo sería costoso, cada nodo contiene en su lugar un mapa de bits de N bits de longitud, donde cada bit indica la presencia de un puntero no nulo. A continuación, se encuentra una matriz de punteros cuya longitud es igual al número de unos en el mapa de bits (su peso de Hamming ).

Ventajas de los HAMT

El trie mapeado por matriz hash alcanza una velocidad casi idéntica a la de una tabla hash, utilizando la memoria de forma mucho más económica. Además, una tabla hash puede requerir un redimensionamiento periódico, una operación costosa, mientras que los HAMT crecen dinámicamente. En general, el rendimiento de los HAMT mejora con una tabla raíz más grande, con un número de ranuras que sea múltiplo de N; algunas variantes de HAMT permiten que la raíz crezca de forma diferida [ 1 ] con un impacto mínimo en el rendimiento.

Detalles de implementación

La implementación de una función HAMT implica el uso de la función de conteo de población , que cuenta la cantidad de unos en la representación binaria de un número. Esta operación está disponible en muchas arquitecturas de conjuntos de instrucciones , pero solo en algunos lenguajes de alto nivel . Si bien el conteo de población se puede implementar en software en tiempo O(1) mediante una serie de instrucciones de desplazamiento y suma , hacerlo puede ralentizar la operación considerablemente.

Implementaciones

Los lenguajes de programación Clojure , [ 2 ] Scala y Frege [ 3 ] utilizan una variante persistente de tries mapeados en matrices hash para su tipo de mapa hash nativo. La biblioteca Haskell "unordered-containers" utiliza la misma para implementar estructuras de datos de mapas y conjuntos persistentes. [ 4 ] Otra biblioteca Haskell, "stm-containers", adapta el algoritmo para su uso en el contexto de la memoria transaccional de software . [ 5 ] También está disponible una biblioteca JavaScript HAMT [ 6 ] basada en la implementación de Clojure. La implementación Rubinius [ 7 ] de Ruby incluye un HAMT, escrito principalmente en Ruby pero con 3 [ 8 ] primitivas. Los mapas grandes en Erlang utilizan una representación HAMT persistente internamente desde la versión 18.0. [ 9 ] El lenguaje de programación Pony utiliza un HAMT para el mapa hash en su paquete de colecciones persistentes. [ 10 ] Las crates im e im-rc, que proporcionan tipos de colecciones persistentes para el lenguaje de programación Rust, utilizan un HAMT para sus tablas hash persistentes y conjuntos hash. [ 11 ]

La versión concurrente sin bloqueo [ 12 ] del árbol de prefijos hash, denominada Ctrie, es una implementación mutable y segura para subprocesos que garantiza el progreso. Se ha demostrado que la estructura de datos es correcta [ 13 ] : se ha comprobado que las operaciones de Ctrie poseen las propiedades de atomicidad , linealizabilidad y ausencia de bloqueo .

Trabajos posteriores

En 2017, Michael Steindorfer presentó CHAMP (Compressed Hash-Array Mapped Prefix-tree) [ 14 ] , una evolución de HAMT que utiliza menos espacio y mejora el rendimiento para algunas operaciones, principalmente la iteración y la prueba de igualdad (comparación de dos colecciones). La principal diferencia es que, mientras que un nodo HAMT utiliza un único mapa de bits y vector de almacenamiento tanto para los elementos como para los nodos hijos, CHAMP utiliza mapas de bits separados para los elementos y los nodos hijos (no deben tener bits 1 en común) y almacena los elementos y los nodos hijos en diferentes regiones del vector.

Véase también

Referencias

  1. ^ Phil Bagwell ( 2000) . Árboles de hachís ideales (PDF) (Reporte). Departamento de Infociencia, École Polytechnique Fédérale de Lausanne .
  2. "clojure/clojure" . GitHub . 8 de diciembre de 2022.
  3. «Frege/frege» . GitHub . 7 de diciembre de 2022.
  4. Johan Tibell, A. Anunciando contenedores desordenados 0.2
  5. Nikita Volkov, Anuncio de la biblioteca "stm-containers" , 2014
  6. "mattbierner/hamt" . GitHub . 27 de noviembre de 2022.
  7. "Archivo fuente Ruby de HAMT de Rubinius" . GitHub .
  8. https://github.com/rubinius/rubinius/blob/master/machine/builtin/system.cpp#L1724-L1802
  9. "Lenguaje de programación Erlang" .
  10. "horse: Pony es un lenguaje de programación de alto rendimiento, de código abierto, basado en un modelo de actores y con capacidades seguras: Ponylang/ponyc" . GitHub . 26 de noviembre de 2018.
  11. "Documentación de la API para la crate im-rc de Rust" .
  12. Prokopec, A. Implementación de Tries de Hash Concurrentes en GitHub
  13. Prokopec, A. et al. (2011) Cache-Aware Lock-Free Concurrent Hash Tries . Informe técnico, 2011.
  14. Steindorfer, Michael (2017). Colecciones inmutables eficientes (PDF) (tesis doctoral). Centrum Wiskunde & Informatica . Recuperado el 2 de febrero de 2026 .