Pourquoi std :: carte mis en œuvre comme un arbre rouge-noir?

voix
130

Pourquoi std :: carte mis en œuvre comme un arbre rouge-noir ?

Il y a plusieurs équilibrés arbres binaires de recherche (de BSTS) là - bas. Quelles étaient la conception des compromis dans le choix d' un arbre rouge-noir?

Créé 13/03/2011 à 09:33
source utilisateur
Dans d'autres langues...                            


6 réponses

voix
86

Probablement les deux algorithmes d'arbres d'équilibrage auto les plus courantes sont les arbres rouges-noirs et AVL . Pour équilibrer l'arbre après une insertion / mise à jour les deux algorithmes utilisent la notion de rotation où les nœuds de l'arbre sont mis en rotation pour effectuer le rééquilibrage.

Alors que dans les deux algorithmes insertion / suppression des opérations sont O (log n), dans le cas d' un arbre rouge-noir rotation rééquilibre est un O (1) opération alors que AVL c'est un O (log n) le fonctionnement, ce qui rend la arbre rouge-noir plus efficace dans cet aspect de la phase de ré-équilibrage et l' une des raisons possibles qu'il est plus couramment utilisé.

arbres rouges noirs sont utilisés dans la plupart des bibliothèques de collecte, y compris les offres de Java et Microsoft .NET Framework.

Créé 13/03/2011 à 09:47
source utilisateur

voix
2

Il est juste le choix de votre mise en œuvre - ils pourraient être mis en œuvre comme tout arbre équilibré. Les différents choix sont comparables avec des différences mineures. Par conséquent, tout est aussi bon que.

Créé 13/03/2011 à 09:48
source utilisateur

voix
22

AVL ont une hauteur maximale de 1.44logn, tandis que les arbres RB ont un maximum de 2logn. Insertion d'un élément dans un AVL peut impliquer un rééquilibrage à un moment donné dans l'arborescence. Le rééquilibrage se termine l'insertion. Après l'insertion d'une nouvelle feuille, mettre à jour les ancêtres de cette feuille doit être fait jusqu'à la racine, ou jusqu'à un point où les deux sous-arbres sont de profondeur égale. La probabilité d'avoir à mettre à jour les noeuds k est de 1/3 ^ k. Rééquilibrage est O (1). La suppression d'un élément peut impliquer plus d'un rééquilibrage (jusqu'à la moitié de la profondeur de l'arbre).

RB-arbres sont des arbres B d'ordre 4 représentés comme des arbres binaires de recherche. A quatre noeuds dans les résultats B-arbres à deux niveaux dans le BST équivalent. Dans le pire des cas, tous les nœuds de l'arbre sont 2 noeuds, avec une seule chaîne de 3 noeuds vers le bas à une feuille. Cette feuille sera à une distance de 2logn de la racine.

En descendant de la racine au point d'insertion, on doit changer 4 nœuds en 2 nœuds, pour vous assurer que toute insertion ne sature pas une feuille. En revenant de l'insertion, tous ces nœuds doivent être analysés pour vous assurer qu'ils représentent correctement 4 nœuds. Cela peut aussi se faire descendre dans l'arbre. Le coût global sera le même. Il n'y a pas de repas gratuit! Suppression d'un élément de l'arbre est du même ordre.

Tous ces arbres exigent que les noeuds portent des informations sur la taille, le poids, la couleur, etc. Seuls les arbres ébrasés sont exempts de telles informations supplémentaires. Mais la plupart des gens ont peur des arbres ébrasés, en raison de la ramdomness de leur structure!

Enfin, les arbres peuvent aussi comporter des informations de poids dans les noeuds, ce qui permet un équilibrage de poids. Différents schémas peuvent être appliqués. Il faut rééquilibrer quand un sous-arbre contient plus de 3 fois le nombre d'éléments de l'autre sous-arbre. Rééquilibrage est à nouveau fait soit throuh une rotation simple ou double. Cela signifie le pire des cas de 2.4logn. On peut sortir avec 2 fois au lieu de 3, un ratio beaucoup mieux, mais il peut vouloir dire en laissant un peu moins Thant 1% des sous-arbres déséquilibrés ici et là. Rusé!

Quel type d'arbre est le meilleur? AVL sûr. Ils sont les plus simples à coder, et ont leur pire hauteur le plus proche de logn. Pour un arbre de 1000000 éléments, un AVL sera au plus de 29 hauteur, un RB 40 et un poids équilibré 36 ou 50 en fonction du rapport.

Il y a beaucoup d'autres variables: aléatoire, ratio ajoute, supprime, recherches, etc.

Créé 16/07/2011 à 02:52
source utilisateur

voix
36

Cela dépend vraiment de l'utilisation. arbre AVL a généralement plus de rotations rééquilibrage. Donc, si votre application n'a pas trop d'opérations d'insertion et de suppression, mais des poids fortement sur la recherche, puis arbre AVL est probablement un bon choix.

std::map utilise l'arbre rouge-noir qu'il obtient un compromis raisonnable entre la vitesse d'insertion noeud / suppression et la recherche.

Créé 26/05/2012 à 19:32
source utilisateur

voix
2

Mise à jour 14/06/2017: webbertiger modifier sa réponse après avoir commenté. Je tiens à souligner que sa réponse est maintenant beaucoup mieux à mes yeux. Mais je continuais ma réponse comme complément d'information ...

En raison du fait que je pense que la première réponse est fausse (correction: non plus à la fois) et le troisième a une mauvaise affirmation. Je sens que je devais clarifier les choses ...

Les 2 arbres les plus populaires sont AVL et noir Rouge (RB). La principale différence se situent dans l'utilisation:

  • AVL: mieux si le rapport de la consultation (lecture) est plus grande que la manipulation (modification). empreinte mémoire est un peu moins de RB (en raison du bit nécessaire pour la coloration).
  • RB: mieux les cas dans lesquels il y a un équilibre entre la consultation (lecture) et la manipulation (modification) ou plus modification sur la consultation. Une empreinte mémoire légèrement plus grande en raison de la mémorisation de drapeau rouge-noir.

La principale différence vient de la coloration. Vous n'avez moins d'action rééquilibre dans l'arbre RB que AVL parce que la couleur vous permettent de sauter parfois ou raccourcissez les actions rééquilibrer qui ont un coût salut relatif. En raison de la coloration, l'arbre RB ont également le niveau plus élevé de noeuds car il pourrait accepter des noeuds rouges entre les noirs (ayant les possibilités de ~ 2x plus de niveaux) rendant la recherche (lire) un peu moins efficace ... mais parce qu'il est constante (2x), il reste en O (log n).

Si l'on considère le succès de la performance pour une modification d'un arbre (significatif) VS le coup de la performance de la consultation d'un arbre (presque insignifiant), il devient naturel de préférer RB sur AVL pour un cas général.

Créé 30/05/2017 à 20:33
source utilisateur

voix
5

Les réponses précédentes ne portent que sur des alternatives d'arbres et noir rouge reste probablement pour des raisons historiques.

Pourquoi pas une table de hachage?

Dans un arbre un type ne nécessite que d'ordre partiel (<de comparaison) pour être utilisé comme une clé dans la carte. Cependant, les tables de hachage exigent que chaque type de clé a une fonction de hachage définie. Compte tenu de ces exigences de type au minimum est très important pour la programmation générique.

La conception d'une bonne table de hachage nécessite une connaissance intime du contexte, il lequel il sera utilisé. Faut-il utiliser l'adressage ouvert, ou l'enchaînement lié? Quel est le niveau de charge devrait-il accepter avant le redimensionnement? Faut-il utiliser un hachage coûteux qui permet d'éviter les collisions, ou qui est rude et rapide?

(C ++ 11 avons ajouté des tables de hachage avec unordered_map. Vous pouvez voir la documentation qu'il exige la définition des politiques de configurer plusieurs de ces options.)

Étant donné que la STL ne peut pas anticiper ce qui est le meilleur choix pour votre application, la valeur par défaut doit être plus flexible. Les arbres « fonctionnent » et échelle bien.

Qu'en est-il d'autres arbres?

offre Red Black tree rapide recherche et auto en équilibre à la différence BSTS. Un autre utilisateur a ses avantages sur l'arbre AVL auto-équilibrage.

Alexander Stepanov (Le créateur de TSL) a dit qu'il utiliserait un arbre B * au lieu d'un arbre rouge-noir s'il a écrit à std::mapnouveau. En effet , les noeuds peuvent stocker un nombre arbitraire d'éléments qui est plus de façon contiguë convivial pour les caches de mémoire modernes.

Un des plus grands changements depuis a été la croissance des caches. Cache sont misses très coûteux, localité de référence est beaucoup plus important maintenant. structures de données à base de noeud, qui ont une faible localité de référence, font beaucoup moins de sens. Si j'élaboraient aujourd'hui STL, j'aurais un autre ensemble de conteneurs. Par exemple, un est un bien meilleur choix qu'un arbre rouge-noir pour la mise en œuvre d'un conteneur en mémoire associative B * -tree. - Alexander Stepanov

Vous pouvez en lire plus ici

Arbre noir est rouge ou B * toujours le meilleur?

En d' autres occasions Alex a déclaré que std::vectorest presque toujours le meilleur conteneur de liste pour des raisons similaires. Il est rarement judicieux d'utiliser std::listou std::dequemême pour ces situations nous ont été enseignées à l' école (comme la suppression d' un élément du milieu de la liste). std::vectorest si rapide qu'il bat ces structures pour tout , mais un grand n.

En appliquant ce même raisonnement si vous avez seulement un petit nombre d'éléments (centaines?) En utilisant une std::vectoret recherche linéaire peut être plus efficace que la mise en œuvre de l' arbre de std::map. En fonction de la fréquence d'insertion, un TRIEES std::vectorcombiné avec std::binary_searchpeut être le choix le plus rapide.

Créé 22/12/2017 à 00:46
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more