- Structure de données -
Arbres

Un arbre est une structure de données permettant entre autres choses de décrire les relations hiérarchiques entre des objets.

Arbre

On peut par exemple les utiliser afin de représenter des arbres de décision.

Arbre de décision du médecin (simplifié !)

I. Définitions

Un arbre est un type particulier de graphe. A ce titre, un arbre est constitué :

Un arbre est un graphe :

Un arbre, une forêt (plusieurs arbres), un graphe cyclique

Le vocabulaire associé est le suivant (entre parenthèse les traductions en anglais):

Vocabulaire

Un arbre binaire est un arbre tel que chaque noeud possède au maximum deux enfants. On parle alors de fils gauche et de fils droit.

II. Implémentation

Il existe plusieurs façon de représenter les arbres en informatique. L’une des méthode classique est de les définir de façon récursive comme des noeuds pointant vers d’autres noeuds.

La structure de base est alors le noeud. Celui-ci contient :

Implémentation à l’aide de noeuds

L’arbre est tant que tel ne contient alors qu’un seul attribut : sa racine.

Afin de créer un sous-arbre-extrait, on choisit un noeud et on crée un arbre en précisant qu’il est la racine.

III. Algorithmes

1. Hauteur de l’arbre

On peut calculer la hauteur d’un arbre en utilisant une fonction récursive (une fonction qui s’appelle elle-même). Le code ci-dessous correspond au cas de figure d’un arbre binaire.

hauteur(arbre)
    Si arbre est vide :
        Retourner 0
    Sinon :
        Retourner 1 + max(hauteur(Sous-arbre gauche), hauteur(Sous-arbre droit))

2. Taille de l’arbre

On rappelle que la taille d’un arbre est égale au nombre de noeuds non-vides qu’il contient. Là encore il est possible de déterminer la taille à l’aide d’une fonction récursive :

taille(arbre)
    Si arbre est vide :
        Retourner 0
    Sinon :
        Retourner 1 + taille(Sous-arbre gauche) + taille(Sous-arbre droit)

3. Parcours de l’arbre

Il est souvent utile de parcourir l’ensemble des noeuds d’un arbre, ne serait-ce que pour les compter par exemple. Le parcours peut aussi être utile afin de rechercher une valeur dans un arbre.

On distingue globalement deux méthodes de parcours :

L’arbre à parcourir

Sur la figure, le parcours en largeur donnera l’ordre suivant (on convient que les noeuds de gauche sont visités avant ceux de droite) :

\[11 \rightarrow 8 \rightarrow 14 \rightarrow 5 \rightarrow 10 \rightarrow 13 \rightarrow 15\]

Un parcours en profondeur pourra donner :

\[11 \rightarrow 8 \rightarrow 5 \rightarrow 10 \rightarrow 14 \rightarrow 13 \rightarrow 15\]

On peut implémenter un parcours en largeur à l’aide d’une file :

ParcoursLargeur(Graphe G):
    f est une file vide
    Enfiler la racine de G dans f
    Tant que la f est non vide
        Défiler un sommet s de f
        Afficher s
        Pour tout voisin v de s dans G
            Enfiler v dans f
Parcours en largeur

Les parcours en profondeur peuvent eux être définis de façon récursive. Afin de parcourir un arbre, on parcours successivement tous les sous-arbres extraits à partir des enfants de sa racine.On distingue :

ParcoursPréfixe(Graphe G):
    Afficher la racine de G
    Pour tous les enfants e de la racine :
        ParcoursPréfixe( Sous-Arbre de racine e )
Parcours préfixe : on visite les noeuds lorsque l’on passe à leur gauche
ParcoursPostfixe(Graphe G):
    Pour tous les enfants e de la racine :
        ParcoursPréfixe( Sous-Arbre de racine e )
    Afficher la racine de G
Parcours postfixe : on visite les noeuds lorsque l’on passe à leur droite

Remarque : dans le cas des arbres binaires (deux enfants au maximum), on peut définir le parcours infixe dans lequel on visite un noeud entre la visite de l’enfant gauche et celle du droit :

ParcoursInfixe(Graphe G):
    ParcoursPréfixe( Sous-Arbre gauche de la racine de G )
    Afficher la racine de G
    ParcoursPréfixe( Sous-Arbre droit de la racine de G )
Parcours infixe : on visite les noeuds lorsque l’on passe en dessous