Documente Academic
Documente Profesional
Documente Cultură
Arbres
Plan
1. Dfinitions
2. Arbres binaires
3. Arbres de recherche binaires
4. Implmentation en contigu
5. Quelques exemples d'application des arbres binaires
6. Arbres m-aire
1) Dfinitions
Un arbre est une structure de donnes (souvent dynamique) reprsentant un ensemble de valeurs
organises hirarchiquement. Chaque valeur est stocke dans un noeud. Les noeuds sont connects
entre eux par des relations parent/fils.
A part le noeud racine, tous les autres noeuds ont exactement un seul noeud parent et zro ou
plusieurs noeuds fils.
Le noeud racine n'a pas de parent et possde zro ou plusieurs fils.
Les noeuds qui n'ont pas de fils sont appels feuilles (ou noeuds externes), les autres (ceux qui ont
au moins un fils) sont appels noeuds internes.
Niveaux
0
racine
d
f
g
j
h
k
i
l
Dans l'exemple de la figure ci-dessus, la racine de l'arbre est le noeud contenant l'information 'a'.
Les feuilles de cet arbres sont les noeuds contenant respectivement les informations suivantes :
'e', 'c', 'f', 'j', 'k', 'h' et 'l'
Les noeuds contenant les informations 'j' et 'k' sont les fils du noeud contenant 'g' qui est aussi le fils
du noeud contenant 'd', lui mme le fils de la racine.
Les noeuds issus d'un mme parent direct sont des noeuds frres. Dans l'exemple prcdent, les
noeuds contenant 'b', 'c' et 'd' sont frres, de mme que ceux contenant 'f', 'g', 'h' et 'i'. Les noeuds
contenant 'j' et 'k' sont aussi des frres.
Une branche est une suite de noeuds connects de pre en fils (de la racine une feuille). Par
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
exemple a-b-e est une branche de l'arbre prcdent, de mme que a-c, a-d-f, a-d-g-j, ...etc.
Le niveau d'un noeud est la distance qui le spare de la racine. Par exemple, dans la figure
prcdente, le niveau du noeud contenant 'g' est gal 2.
La profondeur d'un arbre (ou sa hauteur) est le plus grand niveau (c-a-d la distance entre la racine et
la feuille la plus lointaine). Dans l'exemple prcdent, la profondeur de l'arbre est gal 3.
- Dfinition rcursive d'un arbre
Cas particulier:
NIL est un arbre (l'arbre vide, contenant zro noeud)
Cas gnral:
si n est un noeud et si T1, T2, ...Tm sont des arbres, alors on peut construire un nouvel
arbre en connectant T1, T2, ...Tm comme des fils n. chaque Ti est dfinit de la mme
manire (rcursivement). T1, T2, ... Tm sont alors des sous-arbres de n
Les descendants d'un noeud n sont tous les noeuds appartenant aux sous-arbres de n. Dans
l'exemple, les descendants de d sont : f,g,h,i,j,k et l.
Les ascendants d'un noeud, sont tous les noeuds dont il est descendant. Dans l'exemple, les
ascendants de k sont : g,d et a.
Le degr d'un noeud est le nombre de ses fils diffrents de NIL. Par exemple le degr de d est 4,
celui de a est 3 alors que le degr de c est 0.
Une fort est un ensemble d'arbres.
2) Arbres binaires
Un arbre binaire est un arbre o chaque noeud est connect deux sous-arbres (un sous-arbre
gauche et un sous-arbre droit). Ainsi le premier fils d'un noeud n est appel fils-gauche (fg) et le
deuxime fils est appel fils-droit (fd).
a
b
fg
fg
fd
fd
fd
fg
d
e
fg
fd
NIL
j
l
Dans cet exemple (la figure ci-dessus), le fils-droit du fils-gauche de la racine est un arbre vide (le
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
NIL droite de b). De mme le sous-arbre droit de la racine est un arbre binaire de racine un noeud
contenant l'information 'c'... etc.
Un arbre binaire est dit 'strictement binaire' si chaque noeud interne a exactement 2 fils diffrents de
NIL. (voir fig. ci-dessous)
d
e
f
b
j
a
Dans un arbre strictement binaire, le nombre de feuilles est toujours gal au nombre de noeuds
internes + 1. Dans l'exemple prcdent, il y a 4 feuilles (e, a, l et b) et 3 noeuds internes (d, f et j).
Un arbre binaire est dit 'complet' (ou compltement quilibr), s'il est strictement binaire et si toutes
les feuilles se trouvent au mme niveau :
d
e
a
f
l
Info( p ) : typeqlq
fg( p ) : ptr
fd( p ) : ptr
Aff-info( p, v )
Aff-fg( p, q )
Aff-fd( p, q )
- Parcours d'arbres
Pour consulter ou faire un traitement particulier au niveau des noeuds d'un arbre binaire, il existe
plusieurs ordres de parcours, parmi lesquels : le prordre, l'inordre et le postordre.
Ce sont des parcours simples dfinir et simples programmer (en rcursif).
Soit n un arbre binaire (pouvant tre vide : n=NIL).
S'il n'est pas vide (n pointe le noeud racine), alors il a la forme suivante (avec T1 et T2 des sousarbres dfinis de la mme manire que n) :
n
val
T1
T2
a) Le parcours prordre de n (s'il n'est pas vide) consiste visiter le noeud racine (n) ensuite
parcourir rcursivement en prordre les sous-arbres T1 puis T2 --> [ n , T1 , T2 ]
Voici une procdure (rcursive) qui affiche les valeurs (informations) de tous les noeuds d'un arbre
de racine R en le parcourant en prordre :
preordre( R:ptr )
debut
SI R <> NIL
ecrire( info(R) );
preordre( fg(R) );
preordre( fd(R) )
FSI
fin
b) Le parcours inordre de n (s'il n'est pas vide) consiste d'abord parcourir rcursivement en
inordre le sous-arbre gauche T1, puis visiter le noeud racine (n) ensuite parcourir rcursivement en
inordre le sous-arbre droit T2 --> [ T1 , n , T2 ]
Voici une procdure (rcursive) qui affiche les valeurs (informations) de tous les noeuds d'un arbre
de racine R en le parcourant en inordre :
inordre( R:ptr )
debut
SI R <> NIL
inordre( fg(R) );
ecrire( info(R) );
inordre( fd(R) )
FSI
fin
c) Le parcours postordre de n (s'il n'est pas vide) consiste d'abord parcourir rcursivement en
postordre les sous-arbres T1 puis T2 ensuite visiter le noeud racine (n) --> [ T1 , T2 , n ]
Voici une procdure (rcursive) qui affiche les valeurs (informations) de tous les noeuds d'un arbre
de racine R en le parcourant en postordre :
postordre( R:ptr )
debut
SI R <> NIL
postordre( fg(R) );
postordre( fd(R) );
ecrire( info(R) )
FSI
fin
Si on applique ces trois parcours sur l'arbre ci-dessous :
a
c
d
f
i
k
j
l
on aura pour le parcours prordre :
abdefjcgiklh
pour le parcours inordre :
edjfbagilkch
et pour le parcours postordre :
ejfdblkighca
remarque : faites beaucoup d'exercices de ce type pour vous familiariser avec ces trois parcours.
On peut faire ces trois parcours sans utiliser la rcursivit, il faudra alors un 'moyen' pour pouvoir
remonter dans les branches de l'arbre. On pourra par exemple utiliser une structure de pile pour
sauvegarder les adresses des noeuds par lesquels on est descendu et les dpiler quand on en aura
besoin pour remonter.
On peut aussi enrichir la structure des noeuds en incluant un pointeur vers le noeud pre, on pourra
alors raliser ces parcours sans utiliser une pile ou une autre structure de sauvegarde.
- Quelques astuces pour raliser un parcours inordre itratif (non rcursif)
On peut remarquer que le premier noeud visit en inordre dans un arbre de racine R, se trouve tre
le noeud le plus gauche dans R (descendre de fg en fg jusqu' trouver un noeud dont le fg est
NIL).
Le suivant inordre d'un noeud n (d'aprs la dfinition rcursive) se trouve dans le sous-arbre droit de
n (s'il existe). C'est donc le noeud le plus gauche du sous-arbre droit de n.
Si le sous-arbre droit de n est vide (fd = NIL), alors le suivant de n se trouve plus haut que n (c'est
un ascendant de n). Pour trouver de quel noeud il s'agit exactement, il faut encore voir la dfinition
rcursive o on remarque qu'un noeud n'est visit ( ecrire(infor(R)) ) qu'aprs avoir terminer le
parcours de son sous-arbre gauche ( inordre(fg(R)) ). Donc le suivant inordre de n quand
fd(n)=NIL, est le premier ascendant gauche de n (s'il existe). C'est dire on remonte partir de n,
de pre en pre, jusqu' trouver un noeud en remontant de son fils gauche.
Maintenant il est facile de raliser le parcours inordre itratif (soit avec une pile soit avec l'opration
pere(n) ) :
On crit une fonction 'Prem_Inordre(R) : ptr' qui recherche le noeud le plus gauche de R, et une
deuxime fonction 'Suiv_Inordre(n:ptr) :ptr' qui retourne le suivant inordre de n.
L'algorithme principal serait alors :
n := Prem_Inordre(R);
TQ n <> NIL
ecrire( info(n) );
n := Suiv_Inordre(n)
FTQ
Il existe d'autres types de parcours, comme par exemple le prordre inverse (n T2 T1), l'inordre
inverse (T2 n T1) et le postordre inverse (T2 T1 n). Tous ces parcours et ceux qu'on dj vu sont
des parcours en profondeur, ils explorent l'arbre branche par branche. Il existe aussi des parcours
dits 'en largeur' qui explorent l'arbre niveau par niveau.
Essayer de lister les valeurs d'un arbre niveau par niveau (en utilisant une file).
3) Arbres de recherche binaires
C'est des arbres binaires utiliss pour acclrer les oprations de recherche, insertion et suppression
de valeurs.
Un arbre binaire de racine R est dit 'de recherche' ssi :
* toutes les valeurs du sous-arbre gauche de R sont infrieurs info(R)
* toutes les valeurs du sous-arbre droit de R sont suprieurs info(R)
* le sous-arbre gauche de R (l'arbre de racine fg(R)) doit tre un arbre de recherche binaire
* le sous-arbre droit de R (l'arbre de racine fd(R)) doit tre un arbre de recherche binaire
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
<
<
>
59
71
>
>
10
33
<
8
>
<
27
20
>
55
<
52
Pour rechercher une valeur v dans un arbre de recherche R, l'algorithme est simple et rapide :
Si l'arbre est vide (R=NIL), on s'arrte (v n'existe pas)
Sinon on compare v avec l'information de la racine (info(R)) :
Si c'est gal, on s'arrte (v existe dans R)
Sinon Si c'est infrieur, on continue rcursivement dans le sous-arbre gauche de R
Sinon c'est suprieur, on continue rcursivement dans le sous-arbre droit de R
On remarque que le parcours inordre d'un arbre de recherche, permet de lister les valeurs de l'arbre
en ordre croissant. Donc le premier noeud en inordre contient la plus petite valeur de l'arbre de
recherche, et le suivant inordre de n contient le successeur en ordre croissant de la valeur info(n).
Pour l'arbre de la figure prcdente, le parcours inordre donne la liste ordonne suivante :
3, 5, 8, 10, 15, 20, 27, 33, 52, 55, 59, 71.
Les oprations d'insertion et de suppression dans un arbre de recherche doivent maintenir la
proprit des arbres de recherche :
Pour insrer une valeur v dans un arbre de recherche R, on commence par rechercher v pour
s'assurer qu'elle n'existe pas dj dans R (pas de double) et pour localiser l'endroit o elle doit tre
insre. Soit p le dernier noeud visit par la recherche, on cre alors un nouveau noeud n contenant
v et on connecte n comme fils-gauche de p si v < info(p) ou comme fils droit de p si v > info(p).
Par exemple si on veut insrer 25 dans l'arbre de la figure prcdente, on commence par rechercher
25, et voici le droulement (textuel) de cette recherche :
on compare 25 par rapport 20 (la racine), c'est suprieur, on descend donc droite,
on compare 25 par rapport 59, c'est infrieur, on descend gauche,
on compare 25 par rapport 27, c'est infrieur, on descend encore gauche et on trouve NIL.
On s'arrte ce niveau, 25 n'existe pas et le dernier noeud visit (p) est celui contenant 27.
Pour insrer 25, il suffit alors de crer un nouveau noeud (n) contenant 25 comme information, et le
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
20
59
15
p
5
3
10
71
27
33
25
55
8
52
L'insertion dans un arbre de recherche cre toujours une nouvelle feuille. L'arbre grandit vers le
bas.
Pour supprimer une valeur v dans un arbre de recherche binaire R, on commence par la rechercher
pour trouver le noeud (n) qui la contient, ensuite on procde la suppression suivant l'un des deux
cas suivants :
a) Si n est une feuille ou bien un noeud interne qui ne possde qu'un seul fils diffrent de NIL, on
peut alors supprimer n en mettant jour son pre (le champs fg ou fd) pour remplacer n soit par
NIL (si c'tait une feuille), soit par l'adresse de l'unique fils de n (sinon).
b) Si n est un noeud avec deux fils diffrents de NIL, on remplace v l'intrieur de n par son
successeur en ordre croissant et on supprime le noeud qui contenait ce successeur. Comme le
successeur de v se trouve dans le suivant inordre de n, il est facile de le localiser, il suffit de
descendre une fois droite de n, puis descendre le plus gauche possible, jusqu trouver un noeud
dont le fg est NIL.
Par exemple, si on supprime 33 dans l'arbre prcdent, on modifie le noeud contenant 27 pour
point directement celui contenant 55 :
20
59
15
71
27
5
10
25
33
55
8
52
Si on supprime la valeur 5 dans l'arbre ci-dessus, on est alors dans le 2e cas (un noeud avec deux
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
fils diffrents de NIL), il faut donc remplacer la valeur 5 par son successeur (8), qui se trouve dans
le noeud le plus gauche du sous-arbre droit de 5. Le noeud contenant 8 sera bien sr supprim
pour ne pas garder de double.
On obtient alors l'arbre suivant :
20
59
15
71
27
5 8
10
8
25
55
52
Toutes les oprations que l'on vient de voir (recherche, insertion et suppression) sont efficaces
(rapides) si l'arbre binaire est quilibr (ou presque), car la profondeur serait alors logarithmique en
fonction du nombre de noeuds (valeurs). Par exemple, dans un arbre de recherche binaire quilibr
contenant 1000 valeurs, il faudrait au maximum 10 tests (ou itrations) pour une recherche,
insertion ou suppression. De mme qu'il en faudrait 20 tests si l'arbre renfermait 1 000 000 de
valeurs, ...etc.
Le problme est que rien n'assure que l'arbre restera toujours quilibr (ou presque), si par exemple
on insre, dans un arbre initialement vide, une suite ordonne de 1000 valeurs, le rsultat obtenu
sera un arbre compltement 'dgnr' qui ressemble en fait une simple liste linaire chane de
1000 maillons. Dans ce cas, le cot des oprations d'accs deviendra linaire (proportionnel au
nombre de valeur), et par exemple une recherche dans un tel arbre coutera au maximum 1000 tests,
alors que dans un arbre dgnr d'un million de valeurs, le cot sera d'un million de tests, ...etc.
Il existe d'autres algorithmes d'insertion et de suppression (un peu plus complexes) permettant de
garder l'arbre quilibr dans tous les cas. Parmi les techniques les plus connues, il y a : AVL-trees,
RedBlack-trees, B-trees, T-trees, ...etc. On verra dans un autre chapitre, la technique des B-trees qui
gnralise l'utilisation des arbres de recherche dans le stockage efficace de donnes volumineuses
en mmoire secondaire.
4) Implmentation des arbres binaire en contigu
On prsente ici, deux diffrentes manires de reprsenter des arbres binaires dans un espace de
stockage statique (tableau).
- Reprsentation standard
Elle ressemble celle utilise pour implmenter des listes linaires chanes dans un tableau.
Les noeuds sont reprsents par les cases d'un tableau ayant une structure d'au moins trois champs :
(info : typeqlq, fg et fd : entier), on peut aussi rajouter un quatrime champs de type boolen pour
indiquer si la case est libre ou occupe :
type
Tcase = structure
info : typeqlq;
fg,fd : entier;
vide : bool
Fin
var
T : tableau[1..N] de Tcase;
Avec cette reprsentation, on peut facilement implmenter le modle standard des arbres binaire.
Si on veut en plus implmenter l'opration pere(n), on peut rajouter un autre champs de type entier
la structure Tcase.
- Reprsentation squentielle
Dans cette reprsentation, on limine les pointeurs entiers (fg,fd et ventuellement pere), en associant
chaque noeud de l'arbre une position fixe prdfinie dans le tableau:
la case d'indice 1 sera toujours rserve au noeud racine de l'arbre,
la case d'indice 2 sera toujours rserve au fg de la racine,
la case d'indice 3 sera toujours rserve au fd de la racine,
....
en gnral, le fg de la case i se trouvera toujours l'indice 2i et le fd de la case i se trouvera toujours
l'indice 2i+1, alors que le pre de la case i il sera toujours positionn la case i div 2.
On obtient ainsi une reprsentation compacte (qui consomme peu d'espace) mais pour laquelle, on
ne peut pas implmenter le modle standard des arbres binaire. C'est pour des utilisations un peu
particulires (voir plus loin : exemples d'applications).
5) Quelques exemples d'applications des arbres binaires
Les arbres binaires sont trs utiliss en programmation pour une multitude d'applications, on donne
ici un aperu sur quelques exemples d'utilisation.
- Reprsentation des expressions arithmtiques
Les expressions arithmtiques peuvent tres reprsentes sous forme d'arbre binaire. Les noeuds
internes contiennent des oprateurs, alors que les feuilles contiennent des valeurs (oprandes).
Par exemple, l'expression 3*((5+1)/2) sera reprsente par l'arbre suivant :
*
3
/
2
+
5
10
Donner un algorithme rcursif pour valuer une expression sous la forme d'un arbre binaire.
- Acclrer l'accs par position dans une liste
On peut utiliser un genre particulier d'arbre de recherche binaire pour rendre l'accs par position
beaucoup plus rapide qu'un s'imple parcours squentiel.
Dans ce type d'arbre, les feuilles contiennent les valeurs d'une liste donne, alors que les noeuds
internes forment un index de position : chaque noeud interne contient un entier dsignant le nombre
de feuilles de son sous-arbre gauche.
Cette information sera utilise pour guider la recherche d'une position donne :
si la position cherche est infrieure ou gale l'information du noeud interne on descend gauche,
sinon on descend droite et en retranche la position cherche l'information du noeud.
5
5-2
3-2
5eme elt
11
0
1
0
0
0
c
1
d
1
a
1
e
L'arbre ci-dessus est un exemple d'un codage longueur variable pouvant tre gnr par
l'algorithme de Huffman.
Dans cet exemple, le code associ au symbole 'a' est 0101, celui associ 'h' est 01000 et celui
associ 'b' est 10.
Avec ce type de codage (reprsent par un arbre), la proprit du prfixe est toujours vrifie:
aucun code n'est le prfixe d'un autre et c'est ce qui permet de dcoder n'importe quelle chane
de bits sans ambiguit.
Par exemple, la chane 1001110101011110 ne peut tre dcode que d'une seule manire, en la
parcourant de gauche droite, on est guid dans l'arbre pour atteindre les feuilles. A chaque fois
qu'on est sur une feuille, on aura dcod le caractre correspondant, on remonte la racine et
continue le parcours de la chane de bit. On obtient alors le message dcod : bcbbbdb
- File de priorit
Une file de priorit est un ensemble o on peut enfiler des valeurs associes des priorits (des
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
12
poids) et quand on dfile un lment, on doit retirer de l'ensemble la valeur ayant la plus forte
priorit.
On peut implmenter de manire efficace ce type d'ensemble l'aide d'un arbre binaire comme suit:
L'arbre est construit niveau par niveau et chaque niveau est rempli de gauche droite.
Les noeuds de l'arbre renferment les lments de la file de priorit tout en respectant la proprit
suivante : pour tout noeud interne p, priorit(p) >= priorit(de ses fils)
Voici un exemple :
25
18
15
8
3
10
17
12
2
14
11
Quand on enfile un nouvel lment, on le rajoute temporairement la premire position libre (c-a-d
ajouter une nouvelle feuille dans le dernier niveau et en partant de gauche droite), ensuite on le
fait remonter par une srie de permutations avec le pre, jusqu' ce que sa proprit soit <= celle
de son pre.
Par exemple, si on enfile un lment de priorit 20, on commence par l'insrer comme fils gauche
de 6 (c'est la premire position libre dans le dernier niveau)
25
18
15
8
3
10
17
12
2
14
11
20
Puis en permute l'lment 20 avec son pre (car 20 > 6), et on continue les permutations avec son
nouveau pre (18) et on s'arrte ce niveau car 20 <= 25
25
20
15
8
3
10
18
17
12
2
14
11
Pour dfiler un lment (le plus prioritaire de l'ensemble), il suffit de retirer la racine de l'arbre.
Notes de cours : Arbres Structures de donnes (Algo2) INI 2008
13
15
8
3
10
18
17
12
2
14
11
15
8
3
10
17
12
2
14
11
Pour implmenter ces oprations de manire efficace, on utilise la reprsentation squentielle des
arbres binaire.
6) Arbres m-aire
Un arbre m-aire d'ordre d est un arbre o chaque noeud peut avoir un nombre de fils compris entre 0
et d. Si l'ordre n'est pas connu, on dit alors simplement un arbre m-aire. Dans ce cas le nombre de
fils est thoriquement illimit.
Pour crire des algorithmes sur ce type d'arbres, on dfini un modle form par les oprations
suivantes :
CreerNoeud( v ) : ptr
LibrerNoeud( p )
info( p ) : typeqlq
Fils( i,p ) : ptr
Aff-info( p,v )
Aff-Fils( i,p,q )
degr( p ) : entier
Aff-degr( p,x )
Dans le cas d'un arbre m-aire, o l'ordre n'est pas connu, l'opration Add-degr(...) n'est pas
implmente. De plus, il n'existe pas de fils NIL dans un tel arbre.
14
- Implmentation dynamique
Si l'ordre de l'arbre n'est pas connu, l'implmentation standard d'un arbre m-aire en dynamique
consiste allouer des noeuds ayant 3 champs : l'information, le premier fils et le frre droit.
a
b
g
i
Si l'ordre est connu, il plus simple de rserver un tableau de d pointeur pour reprsenter les fils.
- Implmentation statique
C'est le mme principe qui est utilis dans l'implmentation dynamique sauf que les noeuds sont
localiss l'intrieur d'un tableau.
Donc soit un tableau 3 champs principaux (info, premier_fils, et frre_droit) dans le cas o l'ordre
est inconnu, soit rserv un tableau de d entier l'intrieur de chaque case du tableau principal si
l'ordre d est connu.
- Arbres de recherche m-aire
C'est la gnralisation des arbres de recherche binaires pour tre utiliss en mmoire secondaire o
les E/S sont buffrises .
Chaque noeud renferme un tableau de d-1 valeurs (ordonnes) et un tableau de d fils, car dans un
arbre de recherche m-aire d'ordre d, le nombre de fils d'un noeud (le degr) est toujours gal au
nombre de valeur stockes + 1.
Ce type de structures de donnes tant le plus souvent utilises comme une organisation de fichiers,
on laissera leur prsentation dans la partie structures de fichiers.
15