Quelles sont les applications des arbres binaires?

323

Je me demande quelles sont les applications particulières des arbres binaires. Pourriez-vous donner de vrais exemples?

Jichao
la source

Réponses:

425

Se chamailler sur les performances des arbres binaires n'a pas de sens - ils ne sont pas une structure de données, mais une famille de structures de données, toutes avec des caractéristiques de performance différentes. Bien qu'il soit vrai que les arbres binaires non équilibrés fonctionnent bien moins bien que les arbres binaires à équilibrage automatique pour la recherche, il existe de nombreux arbres binaires (tels que les essais binaires) pour lesquels "l'équilibrage" n'a pas de sens.

Applications des arbres binaires

  • Arbre de recherche binaire - Utilisé dans de nombreuses applications de recherche où les données entrent / sortent constamment, telles que les objets mapet setdans les bibliothèques de nombreuses langues.
  • Partition d'espace binaire - Utilisée dans presque tous les jeux vidéo 3D pour déterminer quels objets doivent être rendus.
  • Essais binaires - Utilisés dans presque tous les routeurs à large bande passante pour stocker les tables de routeurs.
  • Hash Trees - utilisé dans les programmes p2p et les signatures d'images spécialisées dans lesquelles un hachage doit être vérifié, mais le fichier entier n'est pas disponible.
  • Tas - Utilisé pour implémenter des files d'attente prioritaires efficaces, qui à leur tour sont utilisées pour la planification des processus dans de nombreux systèmes d'exploitation, la qualité de service dans les routeurs et A * (algorithme de recherche de chemin utilisé dans les applications d'IA, y compris la robotique et les jeux vidéo) . Également utilisé dans le tri en tas.
  • Arbre de codage Huffman ( Chip Uni ) - utilisé dans les algorithmes de compression, tels que ceux utilisés par les formats de fichier .jpeg et .mp3.
  • Arbres GGM - Utilisés dans les applications cryptographiques pour générer un arbre de nombres pseudo-aléatoires.
  • Arbre de syntaxe - Construit par des compilateurs et (implicitement) des calculatrices pour analyser les expressions.
  • Treap - Structure de données randomisée utilisée dans les réseaux sans fil et l'allocation de mémoire.
  • Arborescence en T - Bien que la plupart des bases de données utilisent une forme d'arborescence en B pour stocker les données sur le lecteur, les bases de données qui conservent toutes (la plupart) leurs données en mémoire utilisent souvent des arborescences en T pour le faire.

La raison pour laquelle les arbres binaires sont utilisés plus souvent que les arbres n-aires pour la recherche est que les arbres n-aires sont plus complexes, mais n'offrent généralement aucun avantage réel en termes de vitesse.

Dans un arbre binaire (équilibré) avec des mnœuds, passer d'un niveau au suivant nécessite une comparaison, et il y a des log_2(m)niveaux, pour un total de log_2(m)comparaisons.

En revanche, un arbre n-aire nécessitera des log_2(n)comparaisons (à l'aide d'une recherche binaire) pour passer au niveau suivant. Puisqu'il y a des log_n(m)niveaux totaux, la recherche nécessitera log_2(n)*log_n(m)= log_2(m)total de comparaisons. Ainsi, bien que les arbres n-aires soient plus complexes, ils n'offrent aucun avantage en termes de comparaisons totales nécessaires.

(Cependant, les arbres n-aires sont toujours utiles dans des situations de niche. Les exemples qui viennent immédiatement à l'esprit sont les arbres quadruples et autres arbres de partitionnement d'espace, où la division de l'espace en utilisant seulement deux nœuds par niveau rendrait la logique inutilement complexe; et Arborescences B utilisées dans de nombreuses bases de données, où le facteur limitant n'est pas le nombre de comparaisons effectuées à chaque niveau mais le nombre de nœuds pouvant être chargés à partir du disque dur à la fois)

BlueRaja - Danny Pflughoeft
la source
3
> Treap - Structure de données randomisée utilisée dans les réseaux sans fil et l'allocation de mémoire. Comment sont-ils utilisés exactement dans l'allocation de mémoire et les réseaux sans fil?
frp
1
Il existe de nombreuses structures de données et algorithmes utiles qui utilisent le mot "binaire", et "arbre de recherche binaire" en fait partie, mais ce n'est pas la question qui a été posée. À quoi sert un vieil "arbre binaire" ordinaire, pas trié, pas équilibré, pas complet. Juste un vieil arbre aléatoire simple?
Michael Erickson
4
@MichaelErickson Avez-vous, euh, lu la réponse? Parce que c'est exactement la question à laquelle j'ai répondu.
BlueRaja - Danny Pflughoeft
1
Je crois que les Hash Trees sont communément appelés Merkle Trees, au moins au sein des communautés Bitcoin et Ethereum, IPFS, etc.
Duke
1
Dommage que cette réponse contienne tant d'erreurs. Les arbres n-aires sur du matériel moderne sont presque toujours préférables aux arbres binaires. La plupart des applications nommées n'utilisent pas d'arbres binaires.
Stephan Eggermont
290

Lorsque la plupart des gens parlent d'arbres binaires, ils pensent le plus souvent à la recherche binaire arbres de , donc je vais couvrir cela en premier.

Un arbre de recherche binaire non équilibré est en fait utile pour à peine plus que d'éduquer les étudiants sur les structures de données. En effet, à moins que les données n'entrent dans un ordre relativement aléatoire, l'arbre peut facilement dégénérer dans sa forme la plus défavorable, qui est une liste liée, car les arbres binaires simples ne sont pas équilibrés.

Un bon exemple: j'ai dû réparer un logiciel qui chargeait ses données dans un arbre binaire pour les manipuler et les rechercher. Il a écrit les données sous forme triée:

Alice
Bob
Chloe
David
Edwina
Frank

de sorte que, lors de sa relecture, se soit retrouvé avec l'arborescence suivante:

  Alice
 /     \
=       Bob
       /   \
      =     Chloe
           /     \
          =       David
                 /     \
                =       Edwina
                       /      \
                      =        Frank
                              /     \
                             =       =

qui est la forme dégénérée. Si vous cherchez Frank dans cet arbre, vous devrez rechercher les six nœuds avant de le trouver.

Les arbres binaires deviennent vraiment utiles pour la recherche lorsque vous les équilibrez. Cela implique la rotation des sous-arbres à travers leur nœud racine afin que la différence de hauteur entre deux sous-arbres soit inférieure ou égale à 1. L'ajout de ces noms au-dessus d'un à la fois dans un arbre équilibré vous donnera la séquence suivante:

1.   Alice
    /     \
   =       =

 

2.   Alice
    /     \
   =       Bob
          /   \
         =     =

 

3.        Bob
        _/   \_
   Alice       Chloe
  /     \     /     \
 =       =   =       =

 

4.        Bob
        _/   \_
   Alice       Chloe
  /     \     /     \
 =       =   =       David
                    /     \
                   =       =

 

5.           Bob
        ____/   \____
   Alice             David
  /     \           /     \
 =       =     Chloe       Edwina
              /     \     /      \
             =       =   =        =

 

6.              Chloe
            ___/     \___
         Bob             Edwina
        /   \           /      \
   Alice     =      David        Frank
  /     \          /     \      /     \
 =       =        =       =    =       =

Vous pouvez réellement voir des sous-arbres entiers tourner vers la gauche (aux étapes 3 et 6) lorsque les entrées sont ajoutées, ce qui vous donne un arbre binaire équilibré dans lequel la pire des recherches est O(log N)plutôt que la O(N) que donne la forme dégénérée. A aucun moment le plus haut NULL ( =) ne diffère du plus bas par plus d'un niveau. Et, dans le dernier arbre ci-dessus, vous pouvez trouver Frank en ne regardant que trois nœuds ( Chloe, Edwinaet, enfin,Frank ).

Bien sûr, ils peuvent devenir encore plus utiles lorsque vous en faites des arbres multi-voies équilibrés plutôt que des arbres binaires. Cela signifie que chaque nœud contient plus d'un élément (techniquement, ils contiennent N éléments et N + 1 pointeurs, un arbre binaire étant le cas particulier d'un arbre multidirectionnel à 1 voie avec 1 élément et 2 pointeurs).

Avec un arbre à trois, vous vous retrouvez avec:

  Alice Bob Chloe
 /     |   |     \
=      =   =      David Edwina Frank
                 /     |      |     \
                =      =      =      =

Ceci est généralement utilisé pour gérer les clés d'un index d'éléments. J'ai écrit un logiciel de base de données optimisé pour le matériel où un nœud a exactement la taille d'un bloc de disque (disons, 512 octets) et vous mettez autant de clés que possible dans un seul nœud. Dans ce cas, les pointeurs étaient en fait des numéros d'enregistrement dans un fichier d'accès direct à enregistrement de longueur fixe distinct du fichier d'index (donc le numéro d'enregistrement Xpouvait être trouvé en cherchant simplement à le faire X * record_length).

Par exemple, si les pointeurs sont de 4 octets et que la taille de clé est de 10, le nombre de clés dans un nœud de 512 octets est de 36. C'est 36 clés (360 octets) et 37 pointeurs (148 octets) pour un total de 508 octets avec 4 octets perdus par nœud.

L'utilisation de clés multidirectionnelles introduit la complexité d'une recherche en deux phases (recherche multidirectionnelle pour trouver le nœud correct combinée à une petite recherche séquentielle (ou binaire linéaire) pour trouver la clé correcte dans le nœud) mais l'avantage dans faire moins d'E / S disque que cela ne compense.

Je ne vois aucune raison de le faire pour une structure en mémoire, vous feriez mieux de vous en tenir à un arbre binaire équilibré et de garder votre code simple.

Gardez également à l'esprit que les avantages de O(log N)over O(N)n'apparaissent pas vraiment lorsque vos ensembles de données sont petits. Si vous utilisez un arbre multidirectionnel pour stocker les quinze personnes dans votre carnet d'adresses, c'est probablement exagéré. Les avantages viennent lorsque vous stockez quelque chose comme chaque commande de vos cent mille clients au cours des dix dernières années.

L'intérêt de la notation big-O est d'indiquer ce qui se passe à l' Napproche de l'infini. Certaines personnes peuvent ne pas être d'accord, mais il est même possible d'utiliser le tri à bulles si vous êtes sûr que les ensembles de données resteront en dessous d'une certaine taille, tant que rien d'autre n'est facilement disponible :-)


Quant aux autres utilisations des arbres binaires, il en existe un grand nombre, telles que:

  • Tas binaires où les touches supérieures sont supérieures ou égales aux touches inférieures plutôt qu'à gauche de (ou inférieures ou égales à droite);
  • Les arbres de hachage, similaires aux tables de hachage;
  • Arbres de syntaxe abstraits pour la compilation des langages informatiques;
  • Arbres Huffman pour la compression des données;
  • Arbres de routage pour le trafic réseau.

Étant donné la quantité d'explications que j'ai générées pour les arbres de recherche, je suis réticent à entrer dans beaucoup de détails sur les autres, mais cela devrait suffire pour les rechercher, si vous le souhaitez.

paxdiablo
la source
28
+1 Pour une telle réponse, nous avons écrit; en plus de me présenter des arbres multi-voies équilibrés, quelque chose que je n'ai jamais rencontré auparavant.
Tony
3
Je ne suis pas d'accord avec votre affirmation selon laquelle ils ne sont utiles que pour éduquer les élèves. Ils sont très utiles, même en tant que structure de données statique simple. Cependant, c'est une réponse très bien écrite et illustrée, donc +1 pour tout le reste. :-)
Benson
1
Sur le matériel moderne, presque tous les arbres doivent être multi-voies.
Stephan Eggermont
89

L'organisation du code Morse est un arbre binaire.

arbre binaire

Morse

IliasT
la source
4
Ceci est ma réponse préférée. Illustre directement la réduction de la complexité de calcul requise pour atteindre les caractères plus loin dans la liste.
Moustache le
7
J'ai vraiment apprécié cette réponse!
Duncan Edwards
2
Je travaillais pour une entreprise qui fabriquait des filtres pour la radio amateur, cela me ramène «en arrière» ...
JosephDoggie
62

Un arbre binaire est une structure de données arborescente dans laquelle chaque nœud a au plus deux nœuds enfants, généralement distingués comme "gauche" et "droit". Les nœuds avec enfants sont des nœuds parents et les nœuds enfants peuvent contenir des références à leurs parents. En dehors de l'arbre, il y a souvent une référence au nœud "racine" (l'ancêtre de tous les nœuds), s'il existe. Tout nœud dans la structure de données peut être atteint en commençant au nœud racine et en suivant à plusieurs reprises les références à l'enfant gauche ou droit. Dans un arbre binaire, un degré de chaque nœud est au maximum de deux.

Arbre binaire

Les arbres binaires sont utiles, car comme vous pouvez le voir sur l'image, si vous voulez trouver un nœud dans l'arbre, vous n'avez qu'à regarder un maximum de 6 fois. Si vous souhaitez rechercher le nœud 24, par exemple, vous commencerez à la racine.

  • La racine a une valeur de 31, qui est supérieure à 24, vous allez donc au nœud gauche.
  • Le nœud gauche a une valeur de 15, ce qui est inférieur à 24, vous passez donc au nœud droit.
  • Le nœud droit a une valeur de 23, ce qui est inférieur à 24, vous passez donc au nœud droit.
  • Le nœud droit a une valeur de 27, ce qui est supérieur à 24, vous passez donc au nœud gauche.
  • Le nœud gauche a une valeur de 25, qui est supérieure à 24, vous allez donc au nœud gauche.
  • Le nœud a une valeur de 24, qui est la clé que nous recherchons.

Cette recherche est illustrée ci-dessous: Recherche d'arbre

Vous pouvez voir que vous pouvez exclure la moitié des nœuds de l'arbre entier lors du premier passage. et la moitié du sous-arbre gauche sur le second. Cela rend les recherches très efficaces. Si cela a été fait sur 4 milliards d' éléments, il vous suffira de rechercher un maximum de 32 fois. Par conséquent, plus il y a d'éléments dans l'arborescence, plus votre recherche peut être efficace.

Les suppressions peuvent devenir complexes. Si le nœud a 0 ou 1 enfant, il suffit simplement de déplacer certains pointeurs pour exclure celui à supprimer. Cependant, vous ne pouvez pas facilement supprimer un nœud avec 2 enfants. Nous prenons donc un raccourci. Disons que nous voulions supprimer le nœud 19.

Supprimer 1

Comme il n'est pas facile de déterminer où déplacer les pointeurs gauche et droit, nous en trouvons un pour le remplacer. Nous allons dans le sous-arbre de gauche et allons aussi loin que possible à droite. Cela nous donne la deuxième plus grande valeur du nœud que nous voulons supprimer.

Supprimer 3

Maintenant, nous copions tout le contenu de 18, à l'exception des pointeurs gauche et droit, et supprimons le nœud 18 d'origine.

Supprimer 4


Pour créer ces images, j'ai implémenté un arbre AVL, un arbre à équilibrage automatique, de sorte qu'à tout moment, l'arbre ait au plus un niveau de différence entre les nœuds feuilles (nœuds sans enfants). Cela empêche l'arbre de devenir asymétrique et maintient le temps de O(log n)recherche maximal , avec le coût d'un peu plus de temps requis pour les insertions et les suppressions.

Voici un exemple montrant comment mon arbre AVL s'est maintenu aussi compact et équilibré que possible.

entrez la description de l'image ici

Dans un tableau trié, les recherches prendraient toujours O(log(n)), tout comme un arbre, mais l'insertion et la suppression aléatoires prendraient O (n) à la place de l'arbre O(log(n)). Certains conteneurs STL utilisent ces caractéristiques de performance à leur avantage, de sorte que les temps d'insertion et de retrait prennent un maximum O(log n), ce qui est très rapide. Certains de ces conteneurs sont map, multimap, setet multiset.

Un exemple de code pour une arborescence AVL est disponible sur http://ideone.com/MheW8

Drise
la source
5
Vous ne devez rechercher O (log n) que si vous avez affaire à un arbre de recherche binaire (qui est lui-même bien équilibré). Les arbres binaires arbitraires n'ont pas de contraintes d'ordre et un BST aléatoire a une complexité de recherche O (log h ).
dlev
Ce ne sont pas les types stockés dans les conteneurs standard concernés.
Puppy
12

L'application principale est les arbres de recherche binaires . Il s'agit d'une structure de données dans laquelle la recherche, l'insertion et la suppression sont toutes très rapides (à propos des log(n)opérations)

BlueRaja - Danny Pflughoeft
la source
1
Les arbres de recherche binaire ne sont pas une application mais un type particulier d'arbre binaire.
nbro
@nbro: Vous soutenez une sémantique inutile, ce sont deux façons valables de dire la même chose. Notez que "application" ici ne signifie pas la même chose que "application informatique"
BlueRaja - Danny Pflughoeft
Je pense que la question était plus liée aux applications du monde réel et non aux implémentations spécifiques ou aux types particuliers d'arbres binaires. Et btw, le questionneur ne demande pas quelles structures de données sont des arbres binaires particuliers. Ce n'est pas inutile, l'OMI. Mais je suis d'accord, c'est quand même ambigu. Par exemple, dans votre autre réponse, vous mentionnez des arbres de syntaxe, qui est une application de la structure de données arborescente (mais pas nécessairement binaire ) dans une application réelle. Sur la base de votre raisonnement, alors je pourrais énumérer tous les arbres binaires que je connais, nous serions tous heureux à cause de la quantité d'articles.
nbro
11
  • Les arbres binaires sont utilisés dans le codage Huffman , qui sont utilisés comme code de compression.
  • Les arbres binaires sont utilisés dans les arbres de recherche binaires , qui sont utiles pour conserver des enregistrements de données sans beaucoup d'espace supplémentaire.
Chip Uni
la source
11

Un exemple intéressant d'arbre binaire qui n'a pas été mentionné est celui d'une expression mathématique évaluée récursivement. C'est fondamentalement inutile d'un point de vue pratique, mais c'est une façon intéressante de penser à de telles expressions.

Fondamentalement, chaque nœud de l'arbre a une valeur qui lui est inhérente ou qui est évaluée par récursivité en opérant sur les valeurs de ses enfants.

Par exemple, l'expression (1+3)*2peut être exprimée comme suit:

    *
   / \
  +   2
 / \
1   3

Pour évaluer l'expression, nous demandons la valeur du parent. Ce nœud obtient à son tour ses valeurs de ses enfants, un opérateur plus et un nœud qui contient simplement «2». L'opérateur plus obtient à son tour ses valeurs des enfants avec les valeurs «1» et «3» et les ajoute, renvoyant 4 au nœud de multiplication qui renvoie 8.

Cette utilisation d'un arbre binaire s'apparente à une notation polonaise inverse dans un sens, en ce sens que l'ordre dans lequel les opérations sont effectuées est identique. Une autre chose à noter est qu'il ne doit pas nécessairement être un arbre binaire, c'est juste que les opérateurs les plus couramment utilisés sont binaires. À son niveau le plus élémentaire, l'arbre binaire ici n'est en fait qu'un langage de programmation purement fonctionnel très simple.

Aucune idée
la source
9

Je ne pense pas qu'il soit utile d'utiliser des arbres binaires "purs". (sauf à des fins éducatives) Arbres binaires équilibrés, tels que les arbres rouge-noir ou les arbres AVL sont beaucoup plus utiles, car ils garantissent des opérations O (logn). Les arbres binaires normaux peuvent finir par être une liste (ou presque une liste) et ne sont pas vraiment utiles dans les applications utilisant beaucoup de données.

Les arbres équilibrés sont souvent utilisés pour implémenter des cartes ou des ensembles. Ils peuvent également être utilisés pour le tri en O (nlogn), même s'il existe de meilleures façons de le faire.

Vous pouvez également utiliser pour rechercher / insérer / supprimer des tables de hachage , qui ont généralement de meilleures performances que les arbres de recherche binaires (équilibrés ou non).

Une application dans laquelle des arbres de recherche binaires (équilibrés) seraient utiles serait la recherche / l'insertion / la suppression et le tri. Le tri pourrait être en place (presque, en ignorant l'espace de pile nécessaire pour la récursivité), étant donné un arbre équilibré de construction prêt. Ce serait toujours O (nlogn) mais avec un facteur constant plus petit et aucun espace supplémentaire nécessaire (sauf pour le nouveau tableau, en supposant que les données doivent être placées dans un tableau). En revanche, les tables de hachage ne peuvent pas être triées (du moins pas directement).

Peut-être sont-ils également utiles dans certains algorithmes sophistiqués pour faire quelque chose, mais rien ne me vient à l'esprit. Si j'en trouve plus, je modifierai mon message.

D'autres arbres comme les arbres fe B + sont largement utilisés dans les bases de données

George
la source
9

L'une des applications les plus courantes consiste à stocker efficacement les données sous forme triée afin d'accéder et de rechercher rapidement les éléments stockés. Par exemple, std::mapou std::setdans la bibliothèque standard C ++.

L'arbre binaire en tant que structure de données est utile pour diverses implémentations d'analyseurs d'expression et de solveurs d'expression.

Il peut également être utilisé pour résoudre certains problèmes de base de données, par exemple l'indexation.

Généralement, l'arbre binaire est un concept général de structure de données basée sur un arbre particulier et divers types spécifiques d'arbres binaires peuvent être construits avec différentes propriétés.

mloskot
la source
7

En C ++ STL, et de nombreuses autres bibliothèques standard dans d'autres langages, comme Java et C #. Les arbres de recherche binaires sont utilisés pour implémenter set et map.

Yin Zhu
la source
2
en fait, en C ++, les ensembles / cartes sont le plus souvent basés sur des arbres rouge-noir, qui est un arbre de recherche binaire avec quelques restrictions supplémentaires.
Idan K
6

L'une des applications les plus importantes des arbres binaires sont les arbres de recherche binaires équilibrés comme:

Ces types d'arbres ont la propriété que la différence de hauteur entre le sous-arbre gauche et le sous-arbre droit est maintenue petite en effectuant des opérations comme des rotations chaque fois qu'un nœud est inséré ou supprimé.

De ce fait, la hauteur globale de l'arbre reste de l'ordre de log n et les opérations telles que la recherche, l'insertion et la suppression des nœuds sont effectuées en temps O (log n). La STL de C ++ implémente également ces arbres sous forme d'ensembles et de cartes.

rohit
la source
5

Ils peuvent être utilisés comme un moyen rapide de trier les données. Insérez des données dans un arbre de recherche binaire en O (log (n)). Parcourez ensuite l'arbre afin de les trier.

Aaron
la source
2

la syntaxe de vos programmes, ou d'ailleurs beaucoup d'autres choses telles que les langues naturelles peuvent être analysées en utilisant un arbre binaire (mais pas nécessairement).

Anycorn
la source
2

Implémentations de java.util.Set

romain
la source
2

Sur le matériel moderne, un arbre binaire est presque toujours sous-optimal en raison d'un mauvais cache et d'un comportement spatial. Cela vaut également pour les variantes (semi) équilibrées. Si vous les trouvez, c'est là que les performances ne comptent pas (ou sont dominées par la fonction de comparaison), ou plus probablement pour des raisons historiques ou d'ignorance.

Stephan Eggermont
la source
2
Sous-optimal par rapport à quoi?
arbres à plusieurs voies. La recherche linéaire à travers toutes les données que vous obtenez à partir d'un accès à la mémoire est beaucoup plus rapide que de faire un nouvel accès à la mémoire principale
Stephan Eggermont
Je veux vous croire, mais rien dans votre réponse ne vient étayer vos affirmations. Sources, grande notation ou quelque chose. Veuillez développer.
PhilT
@PhilT en.wikipedia.org/wiki/CPU_cache
Stephan Eggermont
0

Un compilateur qui utilise un arbre binaire pour une représentation d'un AST peut utiliser des algorithmes connus pour analyser l'arbre comme postorder, inorder. Le programmeur n'a pas besoin de trouver son propre algorithme. Parce qu'un arbre binaire pour un fichier source est plus élevé que l'arbre n-aire, sa construction prend plus de temps. Prenez cette production: selstmnt: = "if" "(" expr ")" stmnt "ELSE" stmnt Dans un arbre binaire, il aura 3 niveaux de nœuds, mais l'arbre n-aire aura 1 niveau (de chids)

C'est pourquoi les OS basés sur Unix sont lents.

evenhorizon
la source