Il semble que partout où je regarde, les structures de données sont mises en œuvre en utilisant des arbres rouges-noirs ( std::set
en C ++, SortedDictionary
en C #, etc.)
Après avoir couvert (a, b), les arbres rouge-noir et AVL dans mon cours d’algorithme, voici ce que j’ai dégagé (aussi en interrogeant des professeurs, en parcourant quelques livres et en recherchant un peu sur Google):
- La profondeur moyenne des arbres AVL est inférieure à celle des arbres rouge-noir. Par conséquent, la recherche d’une valeur dans l’arbre AVL est toujours plus rapide.
- Les arbres rouge-noir apportent moins de changements structurels pour s'équilibrer que les arbres AVL, ce qui pourrait les rendre potentiellement plus rapides pour l'insertion / suppression. Je dis potentiellement, car cela dépendrait du coût de la modification structurelle de l’arbre, car cela dépendra beaucoup du temps d’exécution et de l’implémentation (pourrait aussi être complètement différent dans un langage fonctionnel lorsque l’arbre est immuable?)
Il existe de nombreux points de repère en ligne qui comparent les arbres AVL et les arbres rouge-noir, mais ce qui m'a frappé est que, selon mon professeur, vous feriez généralement l'une des deux choses suivantes:
- Soit vous ne vous souciez pas vraiment de la performance. Dans ce cas, la différence de 10 à 20% entre AVL et Rouge-Noir dans la plupart des cas n’aura aucune importance.
- Ou bien vous vous souciez vraiment de la performance, dans laquelle vous abandonneriez à la fois les arbres AVL et rouge-noir, et utilisiez les arbres B, qui peuvent être modifiés pour fonctionner beaucoup mieux (ou (a, b)-arbres, je ' Je vais tous les mettre dans le même panier.)
La raison en est qu'un B-tree stocke les données de manière plus compacte dans la mémoire (un nœud contient plusieurs valeurs), le nombre d'erreurs dans le cache sera beaucoup moins important. Vous pouvez également modifier l'implémentation en fonction du cas d'utilisation et rendre l'ordre de l'arborescence B dépend de la taille du cache de la CPU, etc.
Le problème est que je ne trouve pratiquement aucune source capable d'analyser l'utilisation réelle de différentes implémentations d'arbres de recherche sur du matériel réel et moderne. J'ai parcouru de nombreux ouvrages sur les algorithmes et rien trouvé qui puisse comparer différentes variantes d'arborescence, à part montrer que l'une a une profondeur moyenne inférieure à l'autre (ce qui ne dit pas vraiment comment l'arbre se comportera dans de vrais programmes.)
Cela dit, y a-t-il une raison particulière pour laquelle les arbres rouge-noir sont utilisés partout, alors que sur la base de ce qui est dit ci-dessus, les arbres B devraient les surpasser? (en tant que seul point de référence que j'ai pu trouver, montre également les spectacles http://lh3lh3.users.sourceforge.net/udb.shtml , mais il pourrait s'agir simplement d'une mise en œuvre spécifique). Ou est-ce la raison pour laquelle tout le monde utilise des arbres rouge-noir parce qu'ils sont plutôt faciles à mettre en œuvre, ou pour le dire autrement, difficiles à mettre en œuvre de manière médiocre?
Aussi, comment cela change-t-il lorsque l'on passe au royaume des langages fonctionnels? Il semble que Clojure et Scala utilisent des essais mappés sur des tableaux de hachage , où Clojure utilise un facteur de branchement de 32.