Parece que donde quiera que mire, las estructuras de datos se están implementando utilizando árboles rojo-negros ( std::set
en C ++, SortedDictionary
en C #, etc.)
Después de haber cubierto los árboles (a, b), rojo-negro y AVL en mi clase de algoritmos, esto es lo que obtuve (también de preguntar a los profesores, mirar algunos libros y buscar un poco en Google):
- Los árboles AVL tienen una profundidad promedio menor que los árboles rojo-negros, y por lo tanto, buscar un valor en el árbol AVL es consistentemente más rápido.
- Los árboles rojo-negros hacen menos cambios estructurales para equilibrarse que los árboles AVL, lo que podría hacerlos potencialmente más rápidos para insertar / eliminar. Estoy diciendo potencialmente, porque esto dependería del costo del cambio estructural en el árbol, ya que esto dependerá mucho del tiempo de ejecución y la implementación (¿también podría ser completamente diferente en un lenguaje funcional cuando el árbol es inmutable?)
Hay muchos puntos de referencia en línea que comparan AVL y árboles rojo-negros, pero lo que me llamó la atención es que mi profesor básicamente dijo que, por lo general, harías una de dos cosas:
- O realmente no te importa mucho el rendimiento, en cuyo caso la diferencia del 10-20% de AVL vs Rojo-negro en la mayoría de los casos no importará en absoluto.
- O realmente le importa el rendimiento, en el caso de que abandone los árboles AVL y Rojo-negro, y vaya con los árboles B, que se pueden ajustar para que funcionen mucho mejor (o (a, b) -árboles, I ' Voy a poner todo eso en una canasta.)
La razón de esto es porque un árbol B almacena datos de forma más compacta en la memoria (un nodo contiene muchos valores), habrá muchos menos errores de caché. También puede ajustar la implementación en función del caso de uso y hacer que el orden del árbol B dependa del tamaño de la memoria caché de la CPU, etc.
El problema es que no puedo encontrar casi ninguna fuente que analice el uso en la vida real de diferentes implementaciones de árboles de búsqueda en hardware real moderno. He revisado muchos libros sobre algoritmos y no he encontrado nada que compare diferentes variantes de árboles, aparte de mostrar que uno tiene una profundidad promedio menor que el otro (lo que realmente no dice mucho sobre cómo se comportará el árbol). en programas reales.)
Dicho esto, ¿hay alguna razón particular por la que los árboles rojo-negros se estén utilizando en todas partes, cuando se basa en lo que se dijo anteriormente, los árboles B deberían superarlos? (como el único punto de referencia que pude encontrar también muestra http://lh3lh3.users.sourceforge.net/udb.shtml , pero podría ser solo una cuestión de implementación específica). ¿O es la razón por la que todos usan árboles rojo-negros porque son bastante fáciles de implementar o, en otras palabras, difíciles de implementar mal?
Además, ¿cómo cambia esto cuando uno se mueve al ámbito de los lenguajes funcionales? Parece que tanto Clojure como Scala usan intentos mapeados de matriz Hash , donde Clojure usa un factor de ramificación de 32.