Reconnaître une hiérarchie
Un arbre convient quand une donnée contient des sous-parties, qui contiennent elles-mêmes des sous-parties. Il exprime une hiérarchie, là où une liste exprime surtout une suite.
Pensez à un système de fichiers, un menu, des catégories de produits ou des commentaires imbriqués. Chaque élément peut porter une valeur et mener vers plusieurs éléments placés en dessous. Il n'existe pas forcément d'index utile pour atteindre « le troisième élément » : le chemin dans la hiérarchie donne le sens.
Un arbre, concrètement
| Les données ressemblent à… | Réflexe | Pourquoi |
|---|---|---|
| Une suite ordonnée | Liste | Les positions et le voisin suivant dominent. |
| Des niveaux et des sous-parties | Arbre | Chaque nœud ouvre un sous-arbre. |
| Un réseau avec plusieurs routes | Graphe | Un parent unique ne suffit plus. |
Lire un arbre sans ambiguïté
Le vocabulaire décrit une position ou une relation. Comptez toujours des arêtes, pas des nœuds, pour la profondeur et la hauteur.
| Terme | Définition | Dans le dessin précédent |
|---|---|---|
| Nœud | Un élément qui porte une valeur. | src |
| Arête | Le lien entre un parent et un enfant. | projet → docs |
| Racine | Le seul nœud sans parent. | projet |
| Feuille | Un nœud qui n'a aucun enfant. | App.java |
| Profondeur | Le nombre d'arêtes depuis la racine. | App.java : 2 |
| Hauteur | Le plus long chemin vers une feuille en dessous. | src : 1 |
| Sous-arbre | Un nœud et tout ce qui descend de lui. | src + ses fichiers |
La question qui évite les confusions
Pour la profondeur, demandez « à combien d'arêtes suis-je de la racine ? ». Pour la hauteur, demandez « quel est le plus long chemin qui reste jusqu'à une feuille ? ».
L'arbre général : une liste d'enfants
Dans un arbre général, chaque nœud possède une liste d'enfants. Cette liste peut être vide ou contenir autant d'éléments que le domaine le demande.
Le cas local est simple
Affichez la valeur du nœud courant. Une opération sur un arbre commence souvent par ce petit travail local.Chaque enfant pose le même problème
Demandez ensuite à chaque enfant de s'afficher avec une indentation supplémentaire. Le sous-arbre a exactement la même forme que l'arbre entier.La liste vide arrête naturellement
Une feuille n'a aucun enfant. La boucle ne lance donc aucun nouvel appel et la descente s'arrête.
Le bon modèle mental
Ne cherchez pas à mémoriser toute la hiérarchie pendant l'appel. Chaque exécution s'occupe d'un nœud, puis confie chaque sous-arbre à la même méthode. L'annexe sur la récursivité détaille ce mécanisme.
Un sous-arbre est encore un arbre
Chaque enfant est la racine d'un sous-arbre. Chercher dans l'arbre revient donc à chercher de la même façon dans chacun de ces arbres plus petits. Cette répétition du même problème est la récursivité.
Arrêtez une branche vide
Si le nœud vautnull, il n'y a plus rien à chercher, compter ou additionner. C'est le cas de base.Traitez le nœud courant
Comparez sa valeur, comptez-la ou utilisez-la dans le résultat. Chaque appel ne s'occupe que de ce travail local.Confiez les enfants à la même méthode
Appelez la méthode sur chaque enfant. Ces appels appliquent exactement les mêmes trois étapes à des sous-arbres plus petits.Combinez les réponses
Une recherche s'arrête au premier enfant qui répondtrue. Un comptage ou une somme ajoute le résultat de chaque enfant.
Exemple 1 : chercher une valeur partout
Le nœud courant répond d'abord. Sinon, la même recherche part dans le sous-arbre de chaque enfant. Dès qu'une branche trouve la valeur, la méthode retourne true sans examiner les enfants restants.
Exemple 2 : compter les valeurs impaires
Chaque appel compte zéro ou un pour son propre nœud, puis ajoute le compte de chacun de ses enfants. Une branche vide contribue zéro.
Exemple 3 : additionner toutes les valeurs
Seule l'opération locale change. La structure récursive reste la même : cas de base, valeur du nœud courant, appel sur chaque enfant, combinaison des résultats.
| Opération | Branche vide | Nœud courant | Combinaison |
|---|---|---|---|
| Chercher | false | Comparer au target | Tester chaque enfant jusqu'au premier true |
| Compter les impairs | 0 | Ajouter 1 si impair | Ajouter le compte de chaque enfant |
| Additionner | 0 | Prendre la valeur | Ajouter la somme de chaque enfant |
L'arbre est l'un des usages les plus courants de la récursivité
La forme de la donnée et la forme du code se répondent : un arbre contient des sous-arbres, donc la méthode s'appelle elle-même sur ces sous-arbres. Consultez maintenant l'annexe Récursivité pour maîtriser le cas de base et la réduction du problème.
Un arbre binaire n'est pas forcément trié
Un arbre binaire remplace la liste d'enfants par deux références nommées : left et right. Chaque nœud a donc zéro, un ou deux enfants. C'est une contrainte de forme, rien de plus.
Binaire ne veut pas dire trié
Le dessin respecte la limite de deux enfants, mais 12 est à gauche de 8 et 3 à droite. Rien ne permet de choisir une seule direction pour chercher une valeur. Il faut potentiellement regarder des deux côtés.
La boucle sur les enfants montrée plus haut devient ici deux liens nommés. Une recherche générale appelle la même méthode sur left puis right. Sans invariant d'ordre, aucun des deux côtés ne peut être éliminé.
Le BST ajoute un invariant
Un arbre binaire de recherche est un arbre binaire auquel on ajoute une règle d'ordre : toutes les clés du sous-arbre gauche sont plus petites, toutes celles du sous-arbre droit sont plus grandes, et cette règle reste vraie dans chaque sous-arbre.
Arbre général
- Autant d'enfants que nécessaire.
- Exprime directement une hiérarchie libre.
- Aucune direction n'est liée à la valeur.
Arbre binaire
- Au plus deux enfants par nœud.
- Les liens gauche et droite donnent une forme régulière.
- Sans règle supplémentaire, la recherche reste non dirigée.
BST
- Même forme binaire, plus un invariant d'ordre.
- Une comparaison élimine un sous-arbre entier.
- La clé peut piloter une structure clé-valeur.
Une comparaison choisit la direction
Cherchons 30 dans le BST précédent. La comparaison avec le nœud courant suffit à choisir le prochain lien. Avec des chaînes, compareTo donne cette décision : résultat négatif vers la gauche, positif vers la droite, zéro quand la clé est trouvée.
Comparez 30 à 40
30 est plus petit. Descendez uniquement dans le sous-arbre gauche. Le sous-arbre droit de 40 ne peut pas contenir 30 si l'invariant est respecté.Comparez 30 à 20
30 est plus grand. Descendez uniquement à droite de 20.Comparez 30 à 30
Les valeurs sont égales. La recherche se termine après trois comparaisons.
L'invariant est un contrat
La recherche dirigée est correcte seulement si chaque insertion a conservé la règle d'ordre. Une seule clé mal branchée peut devenir invisible à une méthode pourtant bien écrite.
La forme décide du nombre de comparaisons
L'invariant dit où chercher, mais la forme détermine combien de nœuds vous devrez comparer. L'ordre d'insertion peut produire deux arbres valides très différents.
Forme bien répartie
Forme dégénérée
La limite à retenir
Un BST déséquilibré reste correct mais perd le bénéfice de la recherche courte ; des structures auto-équilibrées comme AVL corrigent cette forme, mais leur étude dépasse cette remédiation.
Hors de cette leçon
Vous n'avez pas à mémoriser un catalogue de façons de visiter l'arbre, ni à coder la suppression. Ici, vous devez distinguer les formes, maintenir l'invariant et diriger une recherche.
Écrivez la recherche dirigée
Écrivez maintenant la méthode qui manque. Votre code doit exploiter l'invariant : après chaque comparaison, un seul appel récursif est nécessaire.
Recherche dirigée dans un BST
Écrivez d'abord. Une IA externe pourra ensuite relire votre travail. Son retour peut être faux. Vérifiez-le avec la leçon.
Brouillon enregistré sur cet appareil.
Voir le prompt qui sera copié
Vous corrigez le travail d'un étudiant qui prépare une remédiation Java 17. Évaluez d'abord son raisonnement, ses invariants et la cohérence de son brouillon. Un code incomplet mais bien expliqué mérite un retour utile. Signalez précisément les erreurs sans inventer d'exigences hors sujet. La leçon porte sur l'invariant d'un arbre binaire de recherche. Vérifiez surtout le cas de base, le sens de compareTo, le fait qu'un seul sous-arbre est exploré et la cohérence de la trace. N'exigez aucune autre technique d'arbre. Travail demandé: Complétez contains(Node node, String target). Votre méthode doit : - retourner false quand le nœud est null ; - utiliser target.compareTo(node.key) une seule fois par appel ; - retourner true quand la comparaison vaut zéro ; - descendre à gauche ou à droite, jamais des deux côtés ; - expliquer en une phrase pourquoi cette direction est sûre. Ajoutez ensuite une trace pour la recherche de "Lina" dans cet arbre : Mona à la racine, Hugo à gauche, Sara à droite, Lina à droite de Hugo. Commencez par poser au plus deux questions si une intention reste ambiguë. Donnez ensuite les points corrects, les problèmes précis et la plus petite prochaine étape. Ne fournissez une solution complète que si l'étudiant la demande explicitement. Réponse de l'étudiant: [aucune réponse collée]
Vérifiez vos réflexes
Vérifiez vos réflexes
Une réponse par question. La correction apparaît tout de suite.
Continuez le parcours
La table de hachage et le BST offrent tous deux un accès par clé, mais leur organisation et leurs cas défavorables diffèrent. Pour consolider le mécanisme qui revient dans presque toutes les opérations sur un arbre, poursuivez avec la leçon sur la récursivité.