{clé: valeur}
Les noeuds qui ne sont pas des feuilles sont aussi qualifiés de noeuds internes.
Exemple d'arbre ayant 7 noeuds, 4 feuilles, 6 branches et pour racine : le noeud A.
Les expressions arithmétiques sont représentables sous forme d'arbre binaire. En effet les opérateurs d'addition, de soustraction, de multiplication ou de division sont d'arité 2, c'est-à-dire qu'ils s'appliquent à deux opérandes. Les arbres binaires, par définition d'arité 2, sont donc tout désignés pour les repésenter.
Pour l'Arbre 03, rappelé ci-dessous, on peut aussi imaginer cette structure :
L = [A, B, [C, G, H]]
Ici chaque arbre et sous-arbre est représenté par une liste contenant trois éléments : la racine, le SAG et le SAD.
Reprenons toujours l'exemple de l'Arbre 03. Sa représentation sous forme de dictionnaire peut être :
D = {racine:A, sag:B, sad:{racine:C, sag:G, sad:H}}
Ici, chaque arbre et sous-arbre est un dictionnaire avec trois
clés : la racine, le SAG et le SAD.
class Noeud :
def __init__(self, valeur) :
self.valeur = valeur
self.gauche = None
self.droit = None
a = Noeud("A")
a.gauche = Noeud("B")
a.droit = Noeud("C")
_
en préfixe de leur nom. Ils sont directement modifiables par l'utilisateur. class Arbre:
"""Implémentation de la structure de données «Arbre» en Python."""
# creerArbre(arbre, racine) → arbre
def __init__(self, racine=None):
self._racine = racine # valeur
self._gauche = None # Sous-arbre gauche
self._droit = None # Sous-arbre droit
# estVide(arbre) → booléen
def estVide(self):
return self._racine is None
# racine(arbre) → valeur
def racine(self):
assert not self.estVide(), "L'arbre est vide."
return self._racine
# sag(arbre) → arbre
def sag(self):
return self._gauche
# sad(arbre) → arbre
def sad(self):
return self._droit
# assembler(arbre, arbre, arbre) → arbre
def assembler(self, sag = None, sad = None):
assert not self.estVide(), "L'arbre est vide."
self._gauche = sag
self._droit = sad
# définition de l'impression (print) de l'objet
def __str__(self):
return "({},{},{})".format(self._racine, self._gauche, self._droit)
# définition de l'affichage d'appel de l'objet
def __repr__(self):
return "Arbre()"
# affiche l'arbre binaire dans la console
def afficher(self):
if self.estVide():
print("L'arbre est vide.")
else:
self._afficher(0)
def _afficher(self, level):
if self._droit:
self._droit._afficher(level + 1)
print("{}{}".format(' ' * 4 * level, self._racine))
if self._gauche:
self._gauche._afficher(level + 1)
_racine
_gauche
_droit
_
_
__str__()
__repr__()
afficher()
Le parcours en largeur d'un arbre binaire consiste à parcourir l'arbre,
niveau par niveau en partant de la racine en en lisant les noeuds de
gauche à droite.
Le parcours en largeur de l'arbre ci-dessus donne : A-B-C-D-E-F-G-H-I
Pseudo code : L'algorithme de parcours en largeur utilise une file.
f ← file vide
p ← liste vide
Enfiler l'arbre dans f
TANT QUE f n'est pas vide FAIRE
arbre ← défiler f
ajouter la racine de arbre dans p
SI arbre a un fils gauche FAIRE
enfiler le sous-arbre gauche dans f
SI arbre a un fils droit FAIRE
enfiler le sous-arbre droit dans f
RETOURNER p
TAD_Arbre.py
en ajoutant dans les premières lignes l'instruction : from TAD_File import *
parcoursLargeur(self)
Lors du parcours en profondeur d'un arbre, nous passons sur chaque noeud à trois reprises, avant son fils gauche, entre ses deux fils et après son fils droit.
Lorsqu'on traite un noeud dès sa première visite (ronds rouges en cliquant sur l'image),
nous obtenons l'ordre du parcours en profondeur préfixe des noeuds.
Algorithmiquement, cela revient à faire :
[racine] + appel récursif sur SAG + appel récursif sur SAD
Le parcours en profondeur préfixe de l'arbre binaire 06 ci-dessus
donne : A-B-D-E-G-H-C-F-I
Lorsqu'on traite un noeud lors de sa deuxième visite (carrés bleus),
nous obtenons l'ordre du parcours en profondeur infixe des noeud.
Algorithmiquement, cela revient à faire :
appel récursif sur SAG + [racine] + appel récursif sur SAD
Le parcours en profondeur préfixe de l'arbre binaire 06 ci-dessus
donne : D-B-G-E-H-A-C-I-F
Lorsqu'on traite un noeud lors de sa troisième visite (triangles
verts), nous obtenons l'ordre du parcours en profondeur postfixe des noeud.
Algorithmiquement, cela revient à faire :
appel récursif sur SAG + appel récursif sur SAD + [racine]
Le parcours en profondeur postfixe de l'arbre binaire 06 ci-dessus
donne : D-G-H-E-B-I-F-C-A
_parcoursPre(self, liste)
Arbre()
_parcoursInf(self, liste)
Arbre()
_parcoursPost(self, liste)
Arbre()
Pseudo code : Algorithme pour déterminer la taille d'un arbre.
a ← arbreBinaire
FONCTION taille(a):
SI a EST vide:
RETOURNER 0
SINON:
t ← 1
SI a A sag:
t ← t + taille(sag)
SI a A sad:
t ← t + taille(sad)
RETOURNER t
taille(self)
Arbre()
La hauteur (ou la profondeur) d'un noeud est le nombre de branches entre ce noeud et la racine de l'arbre. La hauteur d'un noeud est définit par :
Attention : La convention utilisée ici est : Le niveau de la racine vaut 1 tandis que sa hauteur (ou sa profondeur) valent 0.
Exemple : Dans cet arbre, le noeud "H" est de hauteur 3.
Pour l'instant nos arbres ne sont pas triés (il ne s'agit pas encore d'arbre binaire de recherche). Ainsi, pour savoir où se situe un noeud et en déduire sa hauteur (ou sa profondeur), il faut parcourir tout l'arbre à sa recherche. L'idée ici va être de descendre dans l'arbre, de manière récursive, en partant de la racine (hauteur 0, niveau 1). Pour chaque noeud rencontré, on va enregistrer dans un dictionnaire sa valeur et son niveau.
hauteurNoeud(self, valeur)
_hauteursNoeuds(self, hauteurs, niv)
hauteurNoeud(self, valeur)
niveauNoeud(self, valeur)
hauteurNoeud(self, valeur)
Pseudo code :
dicoN ← dictionnaire vide
a ← arbre binaire
h ← 0
FONCTION hauteursNoeuds(a, dicoN, h):
AJOUTER à dicoN, le couple (racine(a), h)
SI a A un sag :
dicoN ← hauteursNoeuds(sag(a), dicoN, h+1)
SI a A un sad :
dicoN ← hauteursNoeuds(sad(a), dicoN, h+1)
RETOURNER dicoN
hauteur(self)
a ← arbre binaire de recherche
x ← valeur à rechercher
FONCTION rechercher(a, x) :
SI x = racine(a) ALORS
REPONDRE vrai
SINON SI x < racine(a) ALORS
SI a A un sag ALORS
recherche(sag(a), x)
SINON REPONDRE faux
SINON
SI a A un sad ALORS
recherche(sad(a), x)
SINON REPONDRE faux
rechercher(self, valeur)
ajouter(self, valeur)
min(self)
max(self)
supprimer(self, x)
_parent
__init__
nombreFils(self, x)
supprimeFeuille(self, x)
supprimeUnFils(self,x)
supprimeDeuxFils(self, x)