Vous êtes sur la page 1sur 31

03/05/2018

Université Ibn Tofaïl A.U. 2017/2018


Faculté des Sciences
Kénitra

Structure de données
arborescente : Les Arbres

Licence SMI/SMA - S4 Pr. El B. AMEUR

1. Définitions
Déf 1:
Un arbre est une structure de données composée d’un ensemble de
nœuds reliés par des arcs et qui sont organisés sous forme
arborescente. Chaque nœud contient l’information spécifique de
l’application appelée étiquette (valeur ou clé) et des pointeurs vers
d’autres nœuds (d’autres sous-arbres).
Il existe une relation de parenté entre les nœuds. Un nœud père est
situé au dessus de ses nœuds fils. Un père est relié à ses fils par des
arcs.
Exemple:
Un arbre n-aire

1
03/05/2018

1. Définitions
On distingue trois types de nœuds :
les nœuds internes, qui ont des fils ;
les feuilles: les nœuds ne pointant vers aucun autre nœud, les
nœuds qui n'ont pas de fils ;
le nœud racine de l'arbre: le nœud qui n’est pointé par aucun
autre nœud, c’est l'unique nœud ne possédant pas de père.

Traditionnellement, on dessine toujours la racine en haut et les


feuilles en bas.

1. Définitions
Une propriété intrinsèque de la structure des arbres est la récursivité, et
par conséquent les définitions des algorithmes qui les manipulent
s’écrivent très naturellement de manière récursive.
Déf 2: (Récursive)
Un arbre A est:
soit vide;
soit de la forme A = <v, A1, A2, A3, …, Ak>, où v est l’étiquette
du nœud racine A et A1, A2, A3, …, Ak sont des sous-arbres.

Un arbre n-aire

2
03/05/2018

1. Définitions
2. Vocabulaire employé sur les arbres
Niveau : le niveau de la racine est 0. Les autres nœuds ont un
niveau qui est augmenté de 1 par rapport au nœud dont ils
dépendent.
Chemin d'un nœud : On appelle chemin du nœud B la suite des
nœuds par lesquels il faut passer pour aller de la racine vers ce
nœud B.
Longueur d’un chemin : nombre des nœuds du chemin.
Hauteur (profondeur) d’un arbre : c’est le niveau maximum
atteint par la chemin le plus long +1. C’est le maximum des
longueurs des chemins.
Degré d’un nœud : le nombre de fils du nœud.
Degré d’un arbre: le maximum des degrés des nœuds de l’arbre.
Taille : C’est le nombre total de nœuds de l’arbre.

1. Définitions
2. Vocabulaire employé sur les arbres
Exemple:
1 - La racine est le nœud 1 de niveau 0.
- Les nœuds 2 et 3 sont de niveau 1.
2 3 - Chemin de 9 : 1 – 3 – 7 – 9
- 1 – 3 – 7- 9 est un chemin de
4 5 6 7 8 longueur 4
- Hauteur de 9 : h(9)=4
9 - Hauteur de 6 : h(6)=3
- Hauteur de la racine : h(1)=1
- Hauteur de l’arbre : 4
- Degré de 3 : 2
- Degré de l’arbre : 3 (arbre 3-aire)
- Taille de l’arbre : 9
- Les feuilles : 4, 5, 6, 8, 9

3
03/05/2018

2. Exemples d’applications
1. Expression arithmétique : arbre binaire ordonné
Une expression arithmétique ayant des opérateurs binaires peut
être schématisée sous la forme d’un arbre binaire. La Figure
suivante représente l’expression arithmétique :
((a+b) * (c-d) – e)

Arbre ordonné: si l’ordre des sous-arbres est significatif, on dit que


l’arbre est ordonné. L’ordre des sous-arbres (fils d’un nœud) n’est
pas commutatif. Permuter deux sous-arbres change l’expression.

2. Exemples d’applications
2. Arbre lexicographique :
Un arbre lexicographique permet un rangement de mots par ordre
lexical (alphabétique).
Soient à représenter les mots suivants: mais, mars, mer, mon, sa,
son et sel. Les débuts communs peuvent n’être mémoriser qu’une
seule fois sous forme d’un arbre.

4
03/05/2018

2. Exemples d’applications
3. Arbres de répertoire:
Afin que les opérations d’accès, de recherche et de suppression
aux fichiers seront rapide, la mémoire est organiser d’une
manière hiérarchique sous forme d’un arbre de répertoire.

2. Exemples d’applications
3. Arbres généalogique : arbre n-aire
L’arbre généalogique suivant est un arbre de descendance. Julie a
deux enfants : Jonatan et Gontran. Jonatan a trois enfants :
Pauline, Sonia, Paul.
Le degré de l’arbre est de 3 ; l’arbre est dit 3-aire ou n-aire d’une
manière générale. Le degré de chaque nœud est variable puisqu’il
dépend du nombre d’enfants de ce nœud. Julie est la racine de
l’arbre.

5
03/05/2018

3. Arbres Binaires
1. Définition:
Un arbre binaire est un arbre dont chaque nœud a au maximum
deux fils, habituellement appelés «fils gauche» et «fils droit». Il
peut être défini récursivement de la manière suivante :
Un arbre binaire A est
soit vide;
soit de la forme A = <r, FG, FD>, où r est l’étiquette du
nœud racine A et FG et FD sont des sous-arbres binaires
disjoints.

3. Arbres Binaires
2. Spécification abstraite:
Soit A un arbre binaire des éléments de type Telement (type
générique), sa spécification abstraite est donnée par:
Sorte: ArbreBin
Paramètre: Telement
Utilise : Nœud, Entier, Booleen
Opérations:
créerArbreVide: →ArbreBin
racine : ArbreBin →Noeud
filsG : ArbreBin →ArbreBin
filsD : ArbreBin → ArbreBin
construireArbre : Noeudx ArbreBin x ArbreBin →ArbreBin
estVide : ArbreBin →Booleen
estFeuille : ArbreBin →Booleen
contenu: Noeud→Telement
Hauteur : ArbreBin → Entier ; Taille : ArbreBin → Entier

6
03/05/2018

3. Arbres Binaires
2. Spécification abstraite:
Sorte: ArbreBin

Préconditions: A: ArbreBin
racine(A) est définie ssi A ≠Ø
filsG(A) est définie ssi A ≠Ø
filsD(A) est définie ssi A ≠Ø

Axiomes : r :Noeud, fg , fd: ArbreBin


racine(ConstruireArbre(r,fg,fd)) = r
filsG(ConstruireArbre(r,fg,fd)) =fg
filsD(ConstruireArbre(r,fg,fd)) =fd
Hauteur(créerArbreVde())=0
Taille(créerArbreVide())=0

3. Arbres binaires
.3. Spécification opérationnelle:
Un arbre binaire peut se représenter au moyen d’un tableau ou bien
de structures chaînées. Dans les deux cas, il faut définir au
préalable le type abstrait des nœuds. C’est une structure à trois
champs : l’information (appelée aussi clé), le fils gauche et le
fils droit.

A. Implémentation par méthode contiguë :


Cette méthode utilise un tableau qui peut être statique ou
dynamique. L’indice de la racine doit être connu, généralement
on prend 0. Il faut indiquer pour chaque élément le fils gauche et
le fils droit.
Principe : pour chaque élément on stocke les indices du fils
gauche et du fils droit;
Pour cela on doit définir une structure Noeud de la façon
suivante:

7
03/05/2018

3. Arbres binaires
typedef int Telement;
typedef struct Noeud {
Telement info;
int ifg, ifd;
} Noeud;
const int TMAX=6;
Ainsi on définit le tableau des noeuds arbreBin comme suit :
typedef Noeud arbreBin[TMAX];
Remarque :
L’absence de sous arbre gauche ou droit est représenté par la
valeur -1. Un arbre vide est représenté par un tableau dont l’indice
de sous arbre droit et gauche égal à -2.
info 12 1 91 32 67 45 50 7 61 40 82
ifg 1 2 3 -1 5 -1 -1 8 -1 -1 -1 -2 -2
ifd 7 4 -1 -1 6 -1 -1 10 9 -1 -1 -2 -2

3. Arbres binaires
Exemple:

indice 0 1 2 3 4 5 6 7 8 9 10 11 12
info 12 1 91 32 67 45 50 7 61 40 82
ifg 1 2 3 -1 5 -1 -1 8 -1 -1 -1 -2 -2
ifd 7 4 -1 -1 6 -1 -1 10 9 -1 -1 -2 -2

8
03/05/2018

3. Arbres binaires

void creerArbreBin(arbreBin A){


for(int i=0; i<TMAX; i++){
A[i].ifg=-2;A[i].ifd=-2;
A[i].info=0;
}
}

Noeud racine(arbreBin A, int ir){


if (A[ir].ifg==-2)
printf("\nErreur.\n");
else
return A[ir];
}

3. Arbres binaires
int filsG(arbreBin A, int ir){
if (A[ir].ifg==-2){
printf("\nErreur.\n");
return -1;
}else
return A[ir].ifg;
}
int filsD(arbreBin A, int ir){
if (A[ir].ifd==-2){
printf("\nErreur.\n");
return -1;
}else
return A[ir].ifd;
}

9
03/05/2018

3. Arbres binaires
int construireArbre(Noeud Nd, arbreBin A,
int irfg, int irfd){
int i;
Nd.ifg=irfg;//indice de la racine du fils g
Nd.ifd=irfd;//indice de la racine du fils d
i=0;
while((A[i].ifg !=-2)&&(i<TMAX))
i++;
if (i < TMAX){
A[i] = Nd;
return i;//indice du racine
}else{
printf("\nPleinne\n");
return -1;
}}

3. Arbres binaires

int estVide(arbreBin A, int ir){


if ((A[ir].ifd==-2) || (ir==-1))
return 1;
else
return 0;
}

int estFeuille(arbreBin A, int ir){


if ((A[ir].ifg==-1)&&(A[ir].ifd==-1))
return 1;
else
return 0;
}

10
03/05/2018

3. Arbres binaires
int maxi(int a, int b){return (a>b)?a:b;}
int hauteur(arbreBin A, int ir){
if (estVide(A, ir))
return 0;
else
return 1+ maxi(hauteur(A,filsG(A,ir)),
hauteur(A,filsD(A,ir)));
}
int taille(arbreBin A, int ir){
if (estVide(A, ir))
return 0;
else
return 1+ taille(A,filsG(A,ir))+
taille(A,filsD(A,ir));
}

3. Arbres binaires
Exemple 2: Arbre d’une expression arithmétique

11
03/05/2018

B. Implémentation par liste chaînée:


Un arbre binaire est une liste chaînées constituée par des maillons comportant
trois champs :
– un champ de données info ;
– un pointeur vers le nœud fils gauche;
– un pointeur vers le nœud fils droit.

Implémtation:
La déclaration des types constituant le maillon (l’élément de
base d’un arbre) est la suivante :
typedef int Telement;
typedef struct Noeud {
Telement info;
struct Noeud *pfg, *pfd;
} Noeud;

typedef Noeud * arbreBin;


Opérations de base:
arbreBin creerArbreVide(){
return NULL;
}
Noeud racine(arbreBin A){
if (A==NULL){
printf("\nArbre vide\n");
}
return *A;
}

12
03/05/2018

arbreBin filsG(arbreBin A){


if (A==NULL){
printf("\nArbre vide\n");
}
return A->pfg;
}
arbreBin filsD(arbreBin A){
if (A==NULL){
printf("\nArbre vide\n");
}
return A->pfd;
}
int estVide(arbreBin A){
return A==NULL;
}
Telement contenu(arbreBin A){
if (A==NULL)
printf("\nArbre vide\n");
return A->info;
}

La fonction qui permet la construction d’un arbre binaire.

arbreBin ConstArbre (Telement e, arbreBin SAG,


arbreBin SAD){
arbreBin A;
Noeud *Nd;
Nd =(Noeud*)malloc(sizeof(Noeud));
Nd->info=e;
Nd->pfg=SAG;// sous arbre gauche
Nd->pfd=SAD;//sous arbre droit
A=Nd;
return A;
}
int hauteur(arbreBin A){
if (A==NULL)
return 0;
else
return 1 + maxi(hauteur(filsG(A)),
hauteur(filsD(A)));
}

13
03/05/2018

La fonction taille qui determine le nombre des noeuds d’un arbre binaire.

int taille(arbreBin A){


if (A==NULL)
return 0;
else
return 1 + taille(filsG(A))+ taille(filsD(A));
}

4. Parcours d’un arbre binaire:


Un algorithme de parcours d’arbre est un procédé permettant
d’accéder à chaque nœud de l’arbre. Cette opération qui consiste à
retrouver systématiquement tous les nœuds d'un arbre et d'y
appliquer un même traitement.
On distingue deux catégories de parcours d’arbres : les parcours en
profondeur et le parcours en largeur. Dans le parcours en
profondeur, on explore branche par branche alors que dans le
parcours en largeur on explore niveau par niveau.
A. Parcours en profondeur:
Il y a 6 types de parcours possibles (P : père, SAG : sous-arbre
gauche, SAD : sous-arbre droit). Nous ne considérons dans la suite
de ce chapitre que les parcours gauche-droite. Les parcours
droite-gauche s’en déduisent facilement par symétrie.

14
03/05/2018

. A. Parcours en profondeur:
Parcours préfixe.
Le parcours préfixe est décrit récursivement :
Visiter le père (la racine) ;
Visiter le sous-arbre gauche en parcours préfixe;
Visiter le sous-arbre droit en parcours préfixe.

Un affichage préfixe donnerait :


12 - 1 - 91 - 32- 67 – 45- 50 - 7- 61 - 40 - 82

. A. Parcours en profondeur:
Parcours infixe.
Le parcours infixe est décrit récursivement :
Visiter le sous-arbre gauche en parcours infixe;
Visiter le père (la racine) ;
Visiter le sous-arbre droit en parcours infixe.

Un affichage infixe donnerait :


32 - 91 - 1 - 45 - 6 7 - 50 - 12 - 61 - 40 - 7 - 82

15
03/05/2018

. A. Parcours en profondeur:
Parcours postfixe.
Le parcours postfixe est décrit récursivement :
Visiter le sous-arbre gauche en parcours postfixe;
Visiter le sous-arbre droit en parcours postfixe;
Visiter le père (la racine) .

Un affichage postfixe donnerait :


32- 91 - 45 - 50 - 67 - 1 - 40 - 61 - 82 - 7 - 12

void prefixe(arbreBin A){


if (A!=NULL){
printf("-%d-", A->info);
prefixe(A->pfg);
prefixe(A->pfd);
}
}
void infixe(arbreBin A){
if (A!=NULL){
infixe(A->pfg);
printf("-%d-", A->info);
infixe(A->pfd);
}
}
void postfixe(arbreBin A){
if (A!=NULL){
postfixe(A->pfg);
postfixe(A->pfd);
printf("-%d-", A->info);
}
}

16
03/05/2018

A. Parcours en largeur:
Le parcours en largeur des arbres binaires consiste à les visiter
niveau par niveau de gauche à droite. C’est un algorithme classique
consiste à explorer chaque nœud d'un niveau donné de gauche à
droite, puis de passer au niveau suivant. Ce peut être décrit en
utilisant une file.

Un affichage en largeur donnerait :


12 - 1 - 7- 91- 67- 61- 82- 32 - 45 - 50 - 40

4. Parcours d’un arbre binaire

Algorithme de parcours en largeur :


parcoursLargeur(a):
File F //File FIFO
enfiler(a,F) //enfiler la racine a dans la
file F
tant que non vide(F)
nd=défiler(F)
si non vide(nd)
afficher( contenu(nd) )
// enfiler le fils gauche de nd dans F
enfiler( filsG(nd) , F)
// enfiler le fils droit de nd dans F
enfiler( filsD(nd) , F)

17
03/05/2018

4. Arbres binaires particuliers


On définit dans cette section certaines formes particulières d’arbres binaires:
Arbre binaire dégénéré: Un arbre binaire dégénéré ou filiforme est un arbre
formé uniquement par des nœuds qui ont au plus un fils.
Un arbre binaire est dit complet s’il contient 1 nœud au niveau 0, 2 nœuds au
niveau 1, 4 nœuds au niveau 2, , …, 2k nœuds au niveau k. Dans un tel arbre
on dit aussi que chaque niveau est complètement rempli.

Un arbre binaire parfait est un arbre binaire dont tous les niveaux sont
complètement remplis, sauf éventuellement le dernier niveau des feuilles, et dans
ce cas les feuilles sont groupées le plus gauche possible.

32 - 91 - 1 - 45 - 6 7 - 50 - 12 - 61 - 40 - 7 - 82

5. Arbres Binaires de Recherche


Définition:
Un arbre binaire de recherche (ABR) est un arbre binaire possédant récursivement la
propriété suivante :
L'ensemble des valeurs des nœuds est ordonné;
Les valeurs de tous les nœuds du sous arbre gauche d’un nœud X sont
inférieures ou égales à la valeur du nœud X;
Les valeurs de tous les nœuds du sous arbre gauche d’un nœud X sont
inférieures ou égales à la valeur du nœud X;
Les éléments égaux pouvant être arbitrairement placés à gauche ou à droite .

Exemple d’un ABR:

32 - 91 - 1 - 45 - 6 7 - 50 - 12 - 61 - 40 - 7 - 82

18
03/05/2018

5. Arbres Binaires de Recherche


Spécification abstraite:
En plus des opérations du type abstrait arbre binaire on aura :
Sorte: ArbreBR
Paramètre: Telement
Utilise : Nœud, Entier, Booleen
Opérations:

ExisteEl: ArbreBR x Telement →Booleen
Recherche: ArbreBR x Telement → Noeud
RechercheMin : ArbreBR → Noeud //dernière feuille à gauche
RechercheMax : ArbreBR → Noeud //dernière feuille à droite
insererABR: ArbreBR XTelement → ArbreBR
père : ArbreBR X Noeud→ Noued
supprimerABR: Noeud x ArbreBR → ArbreBR
contenu: Noeud→Telement
….

5. Arbres Binaires de Recherche


Sorte: ArbreBR

Préconditions: A: ArbreBR
racine(A) est définie ssi A ≠Ø
filsG(A) est définie ssi A ≠Ø
filsD(A) est définie ssi A ≠Ø

Axiomes : r :Noeud, a, fg , fd: ArbreBR


contenu(racine(filsG(a)))<=contenu(racine(a)) <contenu(racine(filsD(a)))

racine(ConstruireArbre(r,fg,fd)) = r
filsG(ConstruireArbre(r,fg,fd)) =fg
filsD(ConstruireArbre(r,fg,fd)) =fd
Hauteur(créerArbreVde())=0
Taille(créerArbreVide())=0

19
03/05/2018

Spécification opérationnelle :
typedef int Telement;
typedef struct Noeud {
Telement info;
struct Noeud *fg, *fd;
} Noeud;

typedef Noeud * arbreBR;


Opérations de base:
Version recursive:
int existeEl(arbreBR A, Telement e) {
if (A==NULL)
return 0;
else if ( e == A->info)
return 1;
else if ( e < contenu(A))
return existeEl(A->fg, e);
else
return existeEl(A->fd, e);

Version iterative:
int existeElI(arbreBR A, Telement e) {
arbreBR temp;
temp=A;
while((temp != NULL) && (e!= temp->info)){
if (e<temp->info)
temp = temp->fg;
else
temp = temp->fd;
}
return temp !=NULL;
}
Recherche:
Noeud * recherche(arbreBR A, Telement e){
if (A==NULL)
return NULL;
else if ( e == A->info)
return A;
else if ( e < contenu(A))
return recherche(A->fg, e);
else
return recherche(A->fd, e); }

20
03/05/2018

Noeud* minABR(arbreBR A){


if (A==NULL)
return NULL;
else if (A->fg==NULL)
return A;
else
return minABR(A->fg); }
Noeud * minABRi(arbreBR A) {
Noeud* temp;
temp=A;
while((temp != NULL) && ( temp->fg != NULL)){
temp = temp->fg;
}
return temp;
}
Noeud* maxABR(arbreBR A){
if (A==NULL)
return NULL;
else if (A->fd==NULL)
return A;
else
return maxABR(A->fd);}

Création d'un arbre binaire de recherche : opération insererArbreBR


Soit une suite S[1] , S[2] , …, S[n] d'éléments. On désire, à partir de ces
éléments, créer un arbre binaire de recherche.
Principe:
On réalise des insertions successives de chacun des éléments dans un arbre
binaire de la manière suivante :
- S[1] (premier élément considéré) est la racine de l'arbre
- Si S[i] est inférieur à la racine alors on insère S[i] dans le sous arbre
gauche.
- Si S[i] est supérieur ou égal à la racine alors on insère S[i] dans le sous
arbre droit.
Exemple:
On considère la suite d'éléments suivantes :
50, 82, 12, 61, 67, 7, 40, 32.
On crée, par l'insertion successive des
éléments, l'arbre binaire de recherche
suivant :

21
03/05/2018

arbreBR insererArbreBR(arbreBR A, Telement e){


Noeud * nd, *temp;
nd =(Noeud*)malloc(sizeof(Noeud));
nd->info=e; nd->fg=NULL; nd->fd=NULL;
if (A==NULL){
A = nd;
return A;
}else{
temp = A;
while(temp != NULL){
if ( e <= temp->info){
if (temp->fg == NULL){
temp->fg = nd;
return A;
}else
temp = temp->fg;
}else{
if (temp->fd == NULL){
temp->fd = nd;
return A;
}else
temp = temp->fd; }}}}

Suppression d'un nœud dans un ABR : opération supprimerABR


Pour supprimer un nœud Nd plusieurs cas doivent être traité:
- Si le nœud Nd est une feuille: On peut de l'enlever de l'arbre vu qu'elle n'a
pas de fils.

- Si le nœud Nd a un seul fils: On peut l'enlever de l'arbre en le remplaçant


par son fils

22
03/05/2018

Suppression d'un nœud dans un ABR : opération supprimerABR

- Si le nœud Nd a deux fils: Sa valeur sera remplacer par celle du nœud qui a
la plus grande valeur du sous arbre gauche (ou la plus petite valeur du sous-
arbre droit) et de supprimer le nœud associé dans le sous arbre gauche (ou
droit) .

Exemple: Supposons que le nœud à supprimer Nd est de valeur 7 dans le


schéma ci-dessous).
On le remplace alors par son successeur le plus proche, donc le nœud le plus à
gauche du sous arbre droit (le nœud de valeur 9) ou son plus proche
prédécesseur, donc le nœud le plus à droite du sous-arbre gauche (le nœud de
valeur 6).

Suppression d'un nœud dans un ABR : opération supprimerABR


La suppression d’un nœud dans un ABR nécessite la connaissance, en plus de
son adresse, de l’adresse de son père pour le lier avec ses fils. Pour cela nous
proposons de définir une autre fonction interne qui permet de rechercher le
parent d’un nœud donné.

Noeud * pere(arbreBR A, Noeud * Nd){


Noeud *temp;
if (Nd == A)//Le noeud racine n'a pas de père
return NULL;
else{
temp=A;
while((temp->fg != Nd) &&(temp->fd !=Nd)){
if (Nd->info <= temp->info)
temp = temp->fg;
else
temp = temp->fd;
}
return temp;
}
}

23
03/05/2018

arbreBR supprimerArbreBR(Noeud *Nd, arbreBR A){


Noeud *p, *temp;
p=pere(A,Nd);
if((Nd->fg==NULL) &&(Nd->fd==NULL)){
//1er Cas d'une feuille
if(p==NULL){//Nd une racine isolée
free(Nd); return NULL;
}else{
if(p->fg == Nd)
p->fg = NULL;
else
p->fd = NULL;
free(Nd);
return A;
}
}else if((Nd->fg==NULL)||(Nd->fd==NULL)){
//2eme cas Nd a un seul fils

arbreBR supprimerArbreBR(Noeud *Nd, arbreBR A){


}else if((Nd->fg==NULL)||(Nd->fd==NULL)){
//2eme cas Nd a un seul fils
if(p == NULL){// Nd est une racine
if(Nd->fg !=NULL)
A=Nd->fg;
else
A=Nd->fd;
free(Nd); return A;
}else if(Nd->fg != NULL){
// Nd un noeud interne
if(p->fg==Nd)
p->fg = Nd->fg;
else
p->fd = Nd->fg;
}else{// Nd->fd != NULL
if(p->fg==Nd)
p->fg = Nd->fd;
else
p->fd = Nd->fd;
}
free(Nd); return A;

24
03/05/2018

arbreBR supprimerArbreBR(Noeud *Nd, arbreBR A){


Noeud *p, *temp;
p=pere(A,Nd);

}else{// 3eme cas Nd a deux fils


temp = maxABR(Nd->fg);
Nd->info = temp->info;//Remplacer la clef de Nd
p = pere(A,temp);
if (p==Nd)
p->fg = temp->fg;
else
p->fd = temp->fg;
free(temp);// supprimer le noeud temp
return A;
}
}

6. Arbre équilibré : AVL


1. Définition:
Un arbre équilibré appelé aussi AVL (Adelson-Velskii et Landis) est un arbre
binaire de recherche qui a, pour tout nœud, les hauteurs des sous-arbres gauche
et droit diffèrent d’au plus de 1.

Le facteur d'équilibrage d'un nœud est la différence entre la hauteur de son


sous-arbre droit et celle de son sous-arbre gauche.
feq(Nd) = h(filsD(Nd) - h(filsG(Nd)

Un nœud dont le facteur d'équilibrage est +1, 0, ou -1 est équilibré.

Exemple des arbres équilibrés AVL:

25
03/05/2018

2. Rotations et équilibrage:
Chaque fois qu'un nœud est inséré ou supprimé d'un arbre AVL, le facteur
d'équilibrage de chaque nœud le long du chemin depuis la racine jusqu'au nœud
inséré (ou supprimé) doit être recalculé.

Si l'arbre est resté équilibré, il n'y a rien à faire. Si ce n'est pas le cas, on
effectuera des rotations d'équilibrage de manière à obtenir à nouveau un arbre
AVL.
Def: Une rotation est une modification locale d'un arbre binaire. Elle consiste à
échanger un nœud avec l’un de ses fils.
Dans la rotation droite, un nœud devient le fils droit du nœud qui était son fils
gauche.
Dans la rotation gauche, un nœud devient le fils gauche du nœud qui était son
fils droit.

arbreBR rotationG(arbreBR p){


arbreBR q;
q = p->fd;
p->fd = q->fg;
q->fg = p;
return q;
}

arbreBR rotationD(arbreBR q){


arbreBR p;
p = q->fg;
q->fg = p->fd;
p->fd = q;
return p;
}
Remarque : Les rotations ont la propriété de pouvoir être implémentées en temps
constant, et de préserver l'ordre infixe. En d'autres termes, si A est un arbre
binaire de recherche, tout arbre obtenu à partir de A par une suite de rotations
gauche ou droite d'un sous-arbre de A reste un arbre binaire de recherche.

26
03/05/2018

Types de rotations :

Une rotation simple droite est utilisée quand un nœud a un facteur d'équilibrage
inférieur à -1 et que son fils gauche a un facteur d'équilibrage de -1.

Types de rotations :

Une rotation double droite est utilisée quand un nœud a un facteur


d'équilibrage inférieur à -1 et que son fils gauche a un facteur d'équilibrage de
+1. La double rotation droite est une rotation simple gauche du sous-arbre
gauche, suivi d'une rotation simple droite du nœud déséquilibré. Cette opération
est aussi appelée parfois une rotation gauche-droite.

27
03/05/2018

Types de rotations :

Une rotation simple gauche est utilisée quand un nœud a un facteur


d'équilibrage supérieur à +1 et que son fils droit a un facteur d'équilibrage de +1

Types de rotations :

Une rotation double gauche est utilisée quand un nœud a un facteur


d'équilibrage supérieur à +1 et que son fils gauche a un facteur d'équilibrage de
-1. La double rotation gauche est une rotation simple droite du sous-arbre droit,
suivi d'une rotation simple gauche du nœud déséquilibré. Cette opération est
aussi appelée parfois une rotation droite-gauche.

28
03/05/2018

Double rotation:

arbreBR equilibrer(arbreBR A, Noeud* Nd){


int m,n,h; Noeud * temp;
if (Nd==NULL)
return A;
else{
n=hauteur(filsG(Nd));
m=hauteur(filsD(Nd));
if(m-n == 2){//Rotation vers la gauche
h=hauteur(filsD(filsD(Nd)))-
hauteur(filsG(filsD(Nd)));
if (h<0){// Rotation driote-gauche
Nd->fd = rotationD(Nd->fd);
}
Nd=rotationG(Nd);
}else if(m-n == -2){//Rotation vers la droite
h=hauteur(filsD(filsG(Nd)))-
hauteur(filsG(filsG(Nd)));
if (h<0){// Rotation gauche-droite
Nd->fg = rotationG(Nd->fg);
}
Nd=rotationD(Nd);
}
}

29
03/05/2018

arbreBR equilibrer(arbreBR A, Noeud* Nd){


int m,n,h;
Noeud * temp;
if (Nd==NULL)
return A;
else{
...
}
temp = pere(A, Nd);
if(temp==NULL)
return A;
else
return equilibrer(A,temp);
}

4. Insertion/suppression dans un arbre AVL :


L'insertion dans un arbre AVL se déroule en deux étapes :
Tout d'abord, on insère le nœud exactement de la même manière que dans un
arbre binaire de recherche ;
Puis on remonte depuis le nœud inséré vers la racine en effectuant une
rotation sur chaque sous-arbre déséquilibré.

On peut montrer qu'il suffit d'une rotation simple ou d'une double rotation pour
rééquilibrer un arbre AVL après une insertion.

La suppression peut se faire par la même façon que dans les arbres binaires de
recherche puis on fait appel à la fonction equilibrer.

Remarques:
Après chaque insertion ou suppression, il faut appeler la fonction equilibrer
pour équilibrer l’arbre.
La recherche dans un arbre AVL se déroule exactement comme pour un
arbre binaire de recherche, et comme la hauteur d'un arbre AVL est en
O(log(n)), elle se fait donc en O(log(n))..

30
03/05/2018

6. Arbre n-aires

Def: Un arbre n-aire est composé d’un nœud racine est d’un ensemble pouvant être
vide de nœuds fils qui définissent récursivement des sous-arbres n-aires.

Propriètés
Listes : un “successeur” suivant
Arbres binaires : deux “successeurs” ordonnés filsG et filsD
Arbres n-aires : n successeurs fils1,fils2, ..., filsn

Représentation:
Deux cas possibles
Nombre de successeurs borné: on sait à l’avance que chaque sommet aura N
successeurs au plus, dans ce cas l’ensemble des successeurs peut être
représentée par un tableau des sous arbres n-aires. Un arbre est donc est
représenté par un couple (info, tableau-de-fils).
Nombre de successeurs arbitraire : on ne peut pas prévoir à l’avance le
nombre de successeurs, dans ce cas l’ensemble des successeurs est
représentée par une liste chaînée d’arbres. un arbre est représenté donc
comme un couple (info , liste-de-fils).

31

Vous aimerez peut-être aussi