- 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.
On peut par exemple les utiliser afin de représenter des arbres de décision.
Un arbre est un type particulier de graphe. A ce titre, un arbre est constitué :
Un arbre est un graphe :
Le vocabulaire associé est le suivant (entre parenthèse les traductions en anglais):
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.
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 :
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.
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))
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)
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 :
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
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 )
ParcoursPostfixe(Graphe G):
Pour tous les enfants e de la racine :
ParcoursPréfixe( Sous-Arbre de racine e )
Afficher la racine de G
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 )