Parcourir les arbres et rechercher

Calculer taille et hauteur, suivre les parcours et rechercher ou insérer une clé dans un arbre binaire de recherche.

Environ 40 minutes

  • Calculer taille et hauteur
  • Distinguer quatre parcours
  • Rechercher et insérer dans un ABR
Sommaire
  1. Définir l’arbre et les conventions
  2. Parcourir chaque nœud dans un ordre précis
  3. Rechercher et insérer dans un ABR
  4. Relier forme, coût et méthode au bac

Comment retrouver une clé sans examiner tous les éléments d’un arbre ?

Un arbre peut être parcouru pour tout visiter, ou organisé pour guider une recherche. Ces deux objectifs ne se confondent pas. Nous rappellerons sa représentation récursive, suivrons quatre parcours et construirons une recherche puis une insertion dans un arbre binaire de recherche. Prérequis : fonctions récursives, classes simples, piles et files. Les arbres étudiés sont finis, sans cycle, et les clés des ABR sont des entiers distincts.

Définir l’arbre et les conventions

Un arbre binaire est vide, ou constitué d’une racine et de deux sous-arbres binaires disjoints, gauche et droit. Les positions gauche et droite sont distinctes : un enfant droit seul n’est pas un enfant gauche. Une feuille est un nœud dont les deux sous-arbres sont vides. Un arbre n’est pas simplement un graphe où chaque sommet possède au plus deux voisins : les relations de parenté et l’absence de cycle comptent.

Nous représentons un arbre vide par None. Un objet Noeud porte trois attributs : cle, gauche et droit. Son constructeur reçoit une clé et, éventuellement, deux sous-arbres. Un nœud n’est pas sa seule valeur ; la clé est une donnée stockée dans cet objet. Les algorithmes doivent tester None avant de lire ses attributs.

Python
class Noeud:
  def __init__(
    self, cle,
    gauche=None, droit=None
  ):
    self.cle = cle
    self.gauche = gauche
    self.droit = droit

Dans cet ABR, les clés à gauche d’un nœud sont inférieures à sa clé, celles à droite sont supérieures.

La taille est le nombre de nœuds : zéro pour l’arbre vide, sinon un plus les tailles des deux sous-arbres. La hauteur est ici mesurée en arêtes sur le plus long chemin de la racine à une feuille. Une feuille a donc hauteur zéro ; par convention, le vide a hauteur −1. Certains cours comptent les niveaux : annonce toujours ta convention avant de calculer ou de comparer des résultats.

Les définitions deviennent des programmes : taille du vide renvoie zéro ; sur un nœud, renvoie 1 + taille(gauche) + taille(droit). Pour la hauteur, la base renvoie −1, puis on utilise 1 + max(hauteur(gauche), hauteur(droit)). La récursion termine car chaque appel porte sur un sous-arbre strictement plus petit d’un arbre fini.

Exemple résolu

Calcule la taille et la hauteur de l’arbre dessiné de racine 8.

  1. Étape 1 : Les feuilles 1, 6 et 14 ont taille 1 et hauteur 0.
  2. Étape 2 : Le sous-arbre de racine 3 a taille 3 et hauteur 1 ; celui de racine 10 a taille 2 et hauteur 1.
  3. Étape 3 : La racine apporte un nœud et un niveau au-dessus de ces sous-arbres.

Résultat : La taille est 1 + 3 + 2 = 6 et la hauteur est 1 + max(1, 1) = 2 arêtes.

Piège à éviter : Compter trois niveaux sans annoncer la convention donnerait un nombre différent pour la même forme.

À toi d'essayer

Un arbre vide reçoit une seule clé par insertion. Donne sa taille et sa hauteur avec la convention de la leçon.

Voir la réponse

Il devient une feuille : taille 1, hauteur 0. Le passage de la hauteur −1 à 0 correspond à la convention choisie pour le vide.

Parcourir chaque nœud dans un ordre précis

Les parcours en profondeur explorent entièrement un sous-arbre avant l’autre. La place du traitement de la racine donne leur nom : préfixe pour racine puis gauche puis droit ; infixe pour gauche puis racine puis droit ; suffixe, aussi appelé postfixe, pour gauche puis droit puis racine. À chaque étape, gauche et droit désignent des parcours complets des sous-arbres, pas seulement leurs racines.

Un parcours peut afficher une clé, l’ajouter à une liste ou effectuer un autre traitement. Pour séparer le calcul de l’affichage, construisons une liste resultat reçue comme accumulateur. Le cas vide ne modifie rien. Le programme préfixe ajoute la clé, traite le sous-arbre gauche, puis le droit. Une liste neuve doit être créée avant chaque parcours indépendant.

Python
def prefixe(arbre, resultat):
  if arbre is not None:
    resultat.append(arbre.cle)
    prefixe(arbre.gauche, resultat)
    prefixe(arbre.droit, resultat)

Pour l’infixe, déplace seulement la ligne append entre les deux appels ; pour le suffixe, place-la après les deux appels. Les appels restent gauche puis droit. Le résultat de prefixe n’est pas la liste : la fonction la modifie et renvoie implicitement None. On l’utilise donc avec resultat = [], puis prefixe(arbre, resultat), et on lit ensuite resultat.

Le parcours en largeur visite les niveaux dans leur ordre, de gauche à droite à chaque niveau. Il utilise une file : retirer le plus ancien nœud en attente, le traiter, puis ajouter ses enfants gauche et droit non vides à la fin. Dans la bibliothèque collections, deque propose popleft et append pour ces opérations. Une pile utilisée de la même façon ne conserve pas l’ordre en largeur.

Parcourir en largeur avec une file

  1. Si l’arbre est vide, renvoie une liste vide. Sinon place sa racine seule dans une file.
  2. Tant que la file n’est pas vide, retire le premier nœud et ajoute sa clé au résultat.
  3. Ajoute son enfant gauche s’il existe, puis son enfant droit s’il existe, à la fin de la file.
  4. À la fin, renvoie la liste des clés visitées. Chaque nœud a été ajouté et retiré exactement une fois.

Exemple résolu

Donne les quatre parcours de l’arbre de racine 8, sans le modifier.

  1. Étape 1 : En préfixe, traite 8 avant le sous-arbre 3, puis termine par le sous-arbre 10.
  2. Étape 2 : En infixe, termine le sous-arbre 3 avant 8 ; en suffixe, attends d’avoir fini les deux sous-arbres pour traiter 8.
  3. Étape 3 : En largeur, visite d’abord 8, puis 3 et 10, puis 1, 6 et 14.

Résultat : Préfixe : 8, 3, 1, 6, 10, 14. Infixe : 1, 3, 6, 8, 10, 14. Suffixe : 1, 6, 3, 14, 10, 8. Largeur : 8, 3, 10, 1, 6, 14.

Piège à éviter : Un parcours en largeur ne termine pas tout le sous-arbre gauche avant de visiter le fils droit de la racine.

À toi d'essayer

Un parcours infixe d’un arbre binaire quelconque donne-t-il toujours une liste croissante ? Justifie avec un contre-exemple de deux nœuds.

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

Rechercher et insérer dans un ABR

Un arbre binaire de recherche, abrégé ABR, respecte une propriété globale : à chaque nœud, toutes les clés du sous-arbre gauche sont plus petites que sa clé et toutes celles du sous-arbre droit sont plus grandes. Chacun des sous-arbres doit respecter la même propriété. Ici les doublons ne sont pas ajoutés. Une autre politique est possible, mais doit être précisée avant l’algorithme.

Pour rechercher une clé, compare-la à la racine. L’égalité donne un succès. Si elle est plus petite, seule la gauche peut la contenir ; si elle est plus grande, seule la droite reste possible. Atteindre le vide donne un échec. Cette élimination d’un sous-arbre entier est justifiée par l’ordre des clés, pas par la forme visuelle du dessin.

Python
def contient(arbre, cle):
  if arbre is None:
    return False
  if cle == arbre.cle:
    return True
  if cle < arbre.cle:
    return contient(arbre.gauche, cle)
  return contient(arbre.droit, cle)

Insérer reprend le même chemin. À la première position vide, on crée une feuille portant la clé. Si la clé existe déjà, l’arbre reste identique selon notre convention. Une fonction qui renvoie la racine du sous-arbre obtenu permet aussi de traiter l’insertion dans le vide : le programme client doit affecter le résultat à sa variable racine.

Python
def inserer(arbre, cle):
  if arbre is None:
    return Noeud(cle)
  if cle < arbre.cle:
    arbre.gauche = inserer(
      arbre.gauche, cle)
  elif cle > arbre.cle:
    arbre.droit = inserer(
      arbre.droit, cle)
  return arbre

Exemple résolu

Recherche 7 dans l’ABR dessiné, puis insère cette clé. Où se trouve le nouveau nœud ?

  1. Étape 1 : 7 < 8 : descends à gauche vers 3. Comme 7 > 3, descends à droite vers 6.
  2. Étape 2 : 7 > 6 : la position droite de 6 est vide ; la recherche conclut que 7 est absent.
  3. Étape 3 : L’insertion crée la feuille 7 à cette position. Elle reste inférieure à 8 et supérieure à 3 et à 6.

Résultat : La nouvelle clé est le fils droit de 6. Après insertion, l’arbre contient 7 nœuds et sa hauteur vaut 3.

Piège à éviter : Ajouter seulement un nœud près de 6 sur le dessin ne suffit pas : il faut respecter toutes les contraintes héritées des ancêtres.

La propriété d’ABR doit être vérifiée pour tous les descendants. Une racine 8, un fils gauche 3 et un fils droit 9 de ce 3 violent la propriété : 9 reste dans le sous-arbre gauche de 8. Les comparaisons entre un parent et ses enfants immédiats ne suffisent donc pas à valider tout l’arbre.

À toi d'essayer

Un arbre contient 9 à la racine et 4 à gauche. On place 12 comme fils droit de 4. Chaque enfant est-il du bon côté de son parent ? L’arbre est-il un ABR ?

Correction détaillée pas à pasDans ce chapitre : 2 corrections détaillées.

Relier forme, coût et méthode au bac

Les mêmes clés peuvent produire des hauteurs différentes selon leur organisation.

Dans un parcours complet, chaque nœud est traité une fois. Avec un traitement constant par nœud et une représentation sans copie des sous-arbres, le temps est linéaire en la taille. Les parcours récursifs utilisent une pile dont la profondeur dépend de la hauteur. La file du parcours en largeur peut contenir beaucoup de nœuds d’un même niveau.

Recherche et insertion dans un ABR suivent un seul chemin. Pour une hauteur h, elles visitent au plus h + 1 nœuds non vides. Dans un arbre équilibré, la hauteur grandit comme le logarithme du nombre de nœuds et la recherche a un coût logarithmique. Dans une chaîne, elle peut visiter tous les nœuds : le pire coût est linéaire. Le seul nom ABR ne garantit donc pas une recherche logarithmique.

L’ordre d’insertion influence cette forme. Insérer 2 puis 1 puis 3 donne une hauteur 1 ; insérer 1 puis 2 puis 3 donne une chaîne de hauteur 2. Pour de grandes suites déjà triées, la même insertion élémentaire crée une structure très déséquilibrée. Les techniques automatiques d’équilibrage ne sont pas nécessaires ici.

Au bac : rendre un raisonnement contrôlable

  1. Déclare la représentation du vide et la convention de hauteur ; distingue clé, nœud et sous-arbre.
  2. Pour un parcours, écris l’ordre de traitement et applique-le récursivement à chaque sous-arbre.
  3. Pour une recherche ou une insertion, note la comparaison à chaque nœud et justifie le sous-arbre éliminé.
  4. Pour le coût, précise s’il s’agit d’un arbre quelconque ou équilibré et si tu comptes tous les nœuds ou un seul chemin.

Teste un arbre vide, une feuille, un seul enfant droit, une clé absente et une clé déjà présente. Après une insertion, contrôle le nouvel infixe et la taille. Une séquence croissante obtenue par infixe est un contrôle utile de l’ordre pour des clés distinctes, mais ne prouve pas à elle seule que toutes les opérations d’une bibliothèque sont correctes.

Vocabulaire

Sous-arbre :
Arbre formé d’un nœud et de ses descendants, ou structure vide à une position.
Parcours :
Ordre de visite des nœuds d’une structure.
ABR :
Arbre dont les clés respectent un ordre strict entre chaque racine et tous les éléments de ses sous-arbres.
Hauteur :
Longueur maximale, en arêtes ici, d’un chemin de la racine à une feuille.

Relier les besoins aux mécanismes

BesoinRéponse
Tout visiterParcours en profondeur ou en largeur.
Trouver une cléUn seul chemin, guidé par les comparaisons dans un ABR.
AjouterCréer une feuille à la position vide déterminée par ce chemin.

À retenir

  • Les positions gauche et droite d’un arbre binaire sont distinctes.
  • Le parcours infixe d’un ABR à clés distinctes produit les clés dans l’ordre croissant.
  • Le coût d’une recherche dans un ABR dépend de sa hauteur.

Fiche de révision

Avant tout calcul, fixe le sens de la hauteur : une feuille vaut ici zéro, et le vide −1.

Pour retenir les parcours en profondeur, place la racine avant, entre ou après les deux appels gauche et droit.

Chercher et insérer suivent les mêmes comparaisons ; seule l’action au vide change, échec ou création.

Questions fréquentes

Un arbre binaire est-il forcément un ABR ?

Non. L’arité décrit les positions d’enfants ; la propriété d’ABR impose en plus un ordre entre les clés de tous les sous-arbres.

Insérer conserve-t-il toujours la hauteur ?

Non. Une nouvelle feuille peut allonger le chemin le plus long ; la taille augmente d’un seulement si la clé était absente.

Et maintenant ?

Tu as lu le cours. L’étape suivante tient en une action.

Relis le coursReprends l’essentiel avant de passer à la suite.

Prolonge l’expérience !

Continue à explorer ce chapitre à travers de nouvelles activités, des défis et des expériences interactives. Avec Premium, l’apprentissage continue !

Ici, tu débloques aussi 2 corrections détaillées.

Parent ? Suivez les progrès de votre enfant.

Tous les cours de NSI