Structure de donn´ ee avanc´ ee
Fili`ere SMI Semestre 4
Mustapha KCHIKECH
Facult´e Poly-disciplinaire Safi Universit´e Cadi Ayyad
2019-2020
D´epartement de Math´ematiques et Informatique
Chapitre I
Les arbres binaires
1 2
4
8 9
5 10 11
3 6 12
7
espace
Fili`ere SMI Semestre 4 Structure de donn´ee avanc´ee
1. Introduction
Unarbreest unestructure de donn´eesparticuli`ere qui sert `astockeret manipulerdes donn´ees dans desensembles dynamiques.
Saparticularit´er´eside dans sonconcept d’organisationde donn´ees d’une mani`ere hi´erarchique.
En effet, l’organisation des donn´ees consiste `arelierlesinformationssur ces donn´ees par le biais desbranchesde l’arbre.
Ceci permet unacc`es rapideaux informations stock´ees dans l’arbre et la possibilit´ed’ajouteret desupprimer, d’une mani`ere ´egalementrapide, des
´
el´ements dans l’arbre.
Par ailleurs, lesstructures de donn´ees arbresrepr´esentent l’un desconcepts algorithmiqueslesplus importantsde l’informatique.
Ils sont utilis´es dansplusieurs types d’applicationsinformatiques.Exempledes utilisations les plus connus est lagestion des syst`emes de bases de donn´ees, l’organisation des syst`emes de fichiers d’un syst`eme d’exploitationou combinatoire des mots,codage, etc.
2. Arbres binaires : 2.1 pr´ esentation g´ en´ erale
On peut pr´esent´e unarbrecomme ´etant unnœudou unesuitedesous-arbres.
Unarbrepeut ˆetre unarbres enracin´e(avecracine) ouarbre non enracin´e(sans racine).
Il existe plusieurs typed’arbres mais, vu leur int´erˆet en informatique, nous allons
´etudierdans ce chapitre seulement lesarbres binaires.
Dans un arbre binaire, unnœudd´esignel’´el´ement de l’informationet les branchesvers d’autresnœuds.
Lesnœudssont reli´es les uns aux autres par desrelations d’ordreou de hi´erarchie.
Ainsi, chaquenœudpourrait avoir unp`ere(nœudqui lui estsup´erieurdans la hi´erarchie),unoudeux fils:fils gaucheetfils droit.
La racineest le nœud qui n’a pas de p`ere, c’est donc la racine de l’arbre. La racine est lenœudquiimpose un sensdeparcoursde l’arbre.
Unnœudquin’a pas de filsest appel´e unefeuille.
Le reste desnœudsde l’arbre seront alors appel´es unnœuds internes.
2. Arbres binaires : 2.1 pr´ esentation g´ en´ erale
Exemple :
racine
nœud interne
nœud interne
feuille feuille
nœud interne
feuille
nœud interne
feuille feuille
2. Arbres binaires : 2.1 pr´ esentation g´ en´ erale
Op´ erations sur les arbres binaires :
Dans unarbre binaire, on peut effectuer plusieursop´erationspar exemple :
1 initialiser un arbre binaire,
2 testersi un arbreest vide,
3 cr´eerl’arbre gaucheetl’arbre droitd’un arbre binaire,
4 parcourirun arbre,
5 ajouterun ´el´ement `a un arbre,
6 supprimerun ´el´ement d’un arbre,
7 r´ecup´ererun ´el´ement d’un arbre,
8 vider un arbre.
9 ...
2. Arbres binaires : 2.2 Implantation
D´ eclaration d’un arbre binaire :
Comme le cas des listes chaˆın´ee, les piles et les files,le langage Cpermet der´ealiser des arbres binaires`a l’aide desstructures.
En effet, chaquenoœudde l’arbre est unobjetconstitu´e : d’un champ de donn´ees,
d’un pointeur vers le fils gauche (sous-arbre gauche).
d’un pointeur vers le fils droit (sous-arbre droit).
Lad´eclaration correspondanteest la suivante, o`u l’on suppose ici que lesvaleurs stock´eesdans l’arbre sont detype entier.
nœud donnees fils gauche fils droit
Code en C
typedef intelement;
structnœud {
element valeur;
structnœud * filsG;
structnœud * filsD;
};
typedef structnœud nœud, * arbreB;
2. Arbres binaires : 2.2 Implantation
D´ eclaration d’un arbre binaire :
Comme le cas des listes chaˆın´ee, les piles et les files,le langage Cpermet der´ealiser des arbres binaires`a l’aide desstructures.
En effet, chaquenoœudde l’arbre est unobjetconstitu´e : d’un champ de donn´ees,
d’un pointeur vers le fils gauche (sous-arbre gauche).
d’un pointeur vers le fils droit (sous-arbre droit).
Lad´eclaration correspondanteest la suivante, o`u l’on suppose ici que lesvaleurs stock´eesdans l’arbre sont detype entier.
nœud donnees fils gauche fils droit
Code en C
typedef intelement;
structnœud {
element valeur;
structnœud * filsG;
structnœud * filsD;
};
typedef structnœud nœud, * arbreB;
2. Arbres binaires : 2.2 Implantation
Cr´ eation et initialisation d’un arbre binaire :
Pourcr´eer un arbre binaire, on doitl’initialiser`aNULL, cela va nous permettre d’allouerlepremier nœud.
L’initialisationd’un arbre binaire, ou lacr´eation d’un arbre binaire, est r´ealis´ee par lafonctionsuivante :
arbreB arbreBVide( ) {
return NULL;
}
Pourtestersi un arbre binaireest vide, on utilise la fonction suivante :
int testerArbreBVide(arbreB a) {
return a==NULL;
}
2. Arbres binaires : 2.2 Implantation
Cr´ eation et initialisation d’un arbre binaire :
Pourcr´eer un arbre binaire, on doitl’initialiser`aNULL, cela va nous permettre d’allouerlepremier nœud.
L’initialisationd’un arbre binaire, ou lacr´eation d’un arbre binaire, est r´ealis´ee par lafonctionsuivante :
arbreB arbreBVide( ) {
return NULL;
}
Pourtestersi un arbre binaireest vide, on utilise la fonction suivante :
int testerArbreBVide(arbreB a) {
return a==NULL;
}
2. Arbres binaires : 2.2 Implantation
Cr´ eation et initialisation d’un arbre binaire :
Pourcr´eer un arbre binaire, on doitl’initialiser`aNULL, cela va nous permettre d’allouerlepremier nœud.
L’initialisationd’un arbre binaire, ou lacr´eation d’un arbre binaire, est r´ealis´ee par lafonctionsuivante :
arbreB arbreBVide( ) {
return NULL;
}
Pourtestersi un arbre binaireest vide, on utilise la fonction suivante : int testerArbreBVide(arbreB a)
{
return a==NULL;
}
2. Arbres binaires : 2.2 Implantation
Cr´ eation et initialisation d’un arbre binaire :
Pourcr´eer un arbre binaire, on doitl’initialiser`aNULL, cela va nous permettre d’allouerlepremier nœud.
L’initialisationd’un arbre binaire, ou lacr´eation d’un arbre binaire, est r´ealis´ee par lafonctionsuivante :
arbreB arbreBVide( ) {
return NULL;
}
Pourtestersi un arbre binaireest vide, on utilise la fonction suivante : int testerArbreBVide(arbreB a)
{
return a==NULL;
}
2. Arbres binaires : 2.2 Implantation
Pourcr´eer un arbre binaire, Ilfaut tout d’abord cr´eerunnœud, ensuite on construit, d’unemani`ere recursive, lessous-arbres gauche et droit.
Pour ceci, nous allons d´efinir deuxfonctionsqui permettent de donner lefils gauche, lefils droitd’unnœudet une fonction qui permet de cr´eer unnœud Fonctions qui donnent le fils gauche et le fils droit d’unnœud:
arbreB filsGauche(arbreB a) {
if(a==NULL) return NULL;
return a->filsG;
}
arbreB filsDroit(arbreB a) {
if(a==NULL) return NULL;
return a->filsD;
} Fonction qui permet decr´eerunnœud:
arbreB creeNoeud(element val,arbreB fg, arbreB fd) {
arbreB a=malloc(sizeof(nœud));
a->valeur=val;
a->filsG=fg;
a->filsD=fd;
return a;
}
2. Arbres binaires : 2.2 Implantation
Pourcr´eer un arbre binaire, Ilfaut tout d’abord cr´eerunnœud, ensuite on construit, d’unemani`ere recursive, lessous-arbres gauche et droit.
Pour ceci, nous allons d´efinir deuxfonctionsqui permettent de donner lefils gauche, lefils droitd’unnœudet une fonction qui permet de cr´eer unnœud Fonctions qui donnent le fils gauche et le fils droit d’unnœud:
arbreB filsGauche(arbreB a) {
if(a==NULL) return NULL;
return a->filsG;
}
arbreB filsDroit(arbreB a) {
if(a==NULL) return NULL;
return a->filsD;
} Fonction qui permet decr´eerunnœud:
arbreB creeNoeud(element val,arbreB fg, arbreB fd) {
arbreB a=malloc(sizeof(nœud));
a->valeur=val;
a->filsG=fg;
a->filsD=fd;
return a;
}
2. Arbres binaires : 2.2 Implantation
Pourcr´eer un arbre binaire, Ilfaut tout d’abord cr´eerunnœud, ensuite on construit, d’unemani`ere recursive, lessous-arbres gauche et droit.
Pour ceci, nous allons d´efinir deuxfonctionsqui permettent de donner lefils gauche, lefils droitd’unnœudet une fonction qui permet de cr´eer unnœud Fonctions qui donnent le fils gauche et le fils droit d’unnœud:
arbreB filsGauche(arbreB a) {
if(a==NULL) return NULL;
return a->filsG;
}
arbreB filsDroit(arbreB a) {
if(a==NULL) return NULL;
return a->filsD;
} Fonction qui permet decr´eerunnœud:
arbreB creeNoeud(element val,arbreB fg, arbreB fd) {
arbreB a=malloc(sizeof(nœud));
a->valeur=val;
a->filsG=fg;
a->filsD=fd;
return a;
}
2. Arbres binaires : 2.2 Implantation
Pourcr´eer un arbre binaire, Ilfaut tout d’abord cr´eerunnœud, ensuite on construit, d’unemani`ere recursive, lessous-arbres gauche et droit.
Pour ceci, nous allons d´efinir deuxfonctionsqui permettent de donner lefils gauche, lefils droitd’unnœudet une fonction qui permet de cr´eer unnœud Fonctions qui donnent le fils gauche et le fils droit d’unnœud:
arbreB filsGauche(arbreB a) {
if(a==NULL) return NULL;
return a->filsG;
}
arbreB filsDroit(arbreB a) {
if(a==NULL) return NULL;
return a->filsD;
} Fonction qui permet decr´eerunnœud:
arbreB creeNoeud(element val,arbreB fg, arbreB fd) {
arbreB a=malloc(sizeof(nœud));
a->valeur=val;
a->filsG=fg;
a->filsD=fd;
return a;
}
2. Arbres binaires : 2.2 Implantation
Pourcr´eer un arbre binaire, Ilfaut tout d’abord cr´eerunnœud, ensuite on construit, d’unemani`ere recursive, lessous-arbres gauche et droit.
Pour ceci, nous allons d´efinir deuxfonctionsqui permettent de donner lefils gauche, lefils droitd’unnœudet une fonction qui permet de cr´eer unnœud Fonctions qui donnent le fils gauche et le fils droit d’unnœud:
arbreB filsGauche(arbreB a) {
if(a==NULL) return NULL;
return a->filsG;
}
arbreB filsDroit(arbreB a) {
if(a==NULL) return NULL;
return a->filsD;
} Fonction qui permet decr´eerunnœud:
arbreB creeNoeud(element val,arbreB fg, arbreB fd) {
arbreB a=malloc(sizeof(nœud));
a->valeur=val;
a->filsG=fg;
a->filsD=fd;
return a;
}
2. Arbres binaires : 2.2 Implantation
Cr´ eation d’un arbre binaire : Ajout d’un ´ el´ ement
Lastructured’un arbre binaire,rendl’op´eration d’Ajout d’un ´el´ementun peu d´elicat.
En effet, il existediff´erentesfac¸onsd’ins´ererun ´el´ement dans un arbre binaire : On ins`ere des ´el´ementsd`es que l’on peut.
On ins`ere des ´el´ements de fac¸on `a obtenir un arbrequi se rapproche le plus possibled’unarbre complet(chaque nœud poss`ede 0 ou 2 fils.), On ins`ere de fac¸on `aavoir une certaine logiquedans l’arbre binaire `a construire.
Lapremi`ere m´ethoded’ajout est laplus simple, d`es que l’on trouve unnœudqui a unfils vide, on y met lesous-arbreque l’on veut ins´erer.
Mais cette m´ethodepr´esente un inconv´enient. En effet, l’arbre construit est un arbretr`es particulierconnu sous le nomd’arbre peigne(arbre o`u tous les fils droit (ou gauche) desnœuds internessont desfeuilles. Voici le code en C de cette m´ethode.
2. Arbres binaires : 2.2 Implantation
Fonction qui ajoute desnœudscˆot´e gauche :
arbreBajouterGElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsG=ajouterGElementArbreB(filsGauche(a), val);
returna;
}
Fonction qui ajoute desnœudscˆot´e droit :
arbreBajouterDElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsD=ajouterDElementArbreB(filsDroit(a), val);
returna;
}
2. Arbres binaires : 2.2 Implantation
Fonction qui ajoute desnœudscˆot´e gauche :
arbreBajouterGElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsG=ajouterGElementArbreB(filsGauche(a), val);
returna;
}
Fonction qui ajoute desnœudscˆot´e droit :
arbreBajouterDElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsD=ajouterDElementArbreB(filsDroit(a), val);
returna;
}
2. Arbres binaires : 2.2 Implantation
Fonction qui ajoute desnœudscˆot´e gauche :
arbreBajouterGElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsG=ajouterGElementArbreB(filsGauche(a), val);
returna;
}
Fonction qui ajoute desnœudscˆot´e droit :
arbreBajouterDElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsD=ajouterDElementArbreB(filsDroit(a), val);
returna;
}
2. Arbres binaires : 2.2 Implantation
Fonction qui ajoute desnœudscˆot´e gauche :
arbreBajouterGElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsG=ajouterGElementArbreB(filsGauche(a), val);
returna;
}
Fonction qui ajoute desnœudscˆot´e droit :
arbreBajouterDElementArbreB(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(filsGauche(a)==NULL) a->filsG=creeNoeud(val,NULL,NULL);
else if(filsDroit(a)==NULL) a->filsD=creeNoeud(val,NULL,NULL);
else
a->filsD=ajouterDElementArbreB(filsDroit(a), val);
returna;
}
2. Arbres binaires : 2.2 Implantation
Ajout d’un ´ el´ ement : arbre binaire de recherche
Onremarquelacr´eation d’arbresavec la premi`ere m´ethode n’est pas pratique.
On pr´esente une autre fac¸on de cr´eer des arbres binaires en se basant sur une logique. Lesarbres binaires de recherche.
Ce type d’arbre, il y a unecoh´erenceentre les nœuds, c’est `a dire que la hierarchiedes nœuds respecte uner`egle.
Pour unarbre binaire de recherchecontenant desentiers, les valeurs des nœuds dessous-arbres gauchesontinf´erieures`a laracinede ce nœud,
et les valeurs dessous-arbres droitsontsup´erieurs`a cetteracine.
Exemple :
18
16
12
11 13
17
16 17
23
22
21
27
2. Arbres binaires : 2.2 Implantation
Ajout d’un ´ el´ ement : arbre binaire de recherche
Fonction qui ajoute desnœudsdans arbre binaire de recherche :
arbreB AjoutarbreRecherche(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(a->valeur >= val)
a->filsG=AjoutarbreRecherche(filsGauche(a), val);
else
a->filsD=AjoutarbreRecherche(filsDroit(a), val);
return a;
}
2. Arbres binaires : 2.2 Implantation
Ajout d’un ´ el´ ement : arbre binaire de recherche
Fonction qui ajoute desnœudsdans arbre binaire de recherche :
arbreB AjoutarbreRecherche(arbreB a, element val) {
if(a==NULL)
a=creeNoeud(val,NULL,NULL);
else if(a->valeur >= val)
a->filsG=AjoutarbreRecherche(filsGauche(a), val);
else
a->filsD=AjoutarbreRecherche(filsDroit(a), val);
return a;
}
2. Arbres binaires : 2.4 Parcours d’un arbre
Pour pouvoirtraiterlesdonn´ees stock´eesdans un arbre binaire, il fautparvenir
`
a atteindrelesnœudscontenants ces donn´ees.
Ceci demandedes m´ethodes ou des algorithmesqui permettentd’explorerun arbre dans le but devisitertous ses nœuds.
Il existedeux m´ethodes de parcoursd’un arbre binaire : le parcours en profondeur :
Le parcours en largeur :
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur
Parcours en profondeur : permet d’explorer l’arbre en explorantjusqu’au bout une branchepour passer `a la suivante.
Dans le parcours en profondeur, ondistingue trois typesde parcours : parcours pr´efixe : On explorela racinede l’arbre, on parcourt tout le sous-arbre de gauche, une fois qu’il n’y a plus de sous-arbre gauche on parcourt les ´el´ements dusous-arbre droit.Parcours RGD
(Racine-Gauche-Droit)
parcours infixe : explore laracineapr`es avoir trait´e lesous-arbre gauche, apr`es traitement de la racine, on traite lesous-arbre droit. Parcours GRD (Gauche-Racine-Droit).
parcours suffixe (ou postfixe) : explore lesous-arbre gauche, lesous-arbre droitpuis laracine.Parcours GDR(Gauche-Droit-Racine).
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours pr´ efixe
Principe : pour chaque nœud, onvisitelaracinepuis lefils gaucheet en dernier lefils droit.
void prcoursPrefixe(arbreB a) {
if(a!=NULL) {
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) prcoursPrefixe(filsGauche(a));
prcoursPrefixe(filsDroit(a));
} }
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours pr´ efixe
Principe : pour chaque nœud, onvisitelaracinepuis lefils gaucheet en dernier lefils droit.
void prcoursPrefixe(arbreB a) {
if(a!=NULL) {
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) prcoursPrefixe(filsGauche(a));
prcoursPrefixe(filsDroit(a));
} }
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours Infixe
Principe : pour chaque nœud, onvisitelefils gauchepuis laracineet en dernier lefils droit.
void prcoursInfixe(arbreB a) {
if(a!=NULL) {
prcoursInfixe(filsGauche(a));
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) prcoursInfixe(filsDroit(a));
} }
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours Infixe
Principe : pour chaque nœud, onvisitelefils gauchepuis laracineet en dernier lefils droit.
void prcoursInfixe(arbreB a) {
if(a!=NULL) {
prcoursInfixe(filsGauche(a));
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) prcoursInfixe(filsDroit(a));
} }
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours suffixe (postefixe)
Principe : pour chaque nœud, onvisitelefils gauchepuis lefils droitet en dernier laracine.
void prcoursSuffixe(arbreB a) {
if(a!=NULL) {
prcoursSuffixe(filsGauche(a));
prcoursSuffixe(filsDroit(a));
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) }
}
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en profondeur : Parcours suffixe (postefixe)
Principe : pour chaque nœud, onvisitelefils gauchepuis lefils droitet en dernier laracine.
void prcoursSuffixe(arbreB a) {
if(a!=NULL) {
prcoursSuffixe(filsGauche(a));
prcoursSuffixe(filsDroit(a));
printf("%d ",a->valeur);//<-- ici visit´e (trait´e) }
}
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en largeur
Le parcours en largeur : permet d’explorer l’arbreniveau par niveau.
L’algorithme du parcours en largeurconsiste`autiliser une filepourgarder en m´emoirelesfilsdunœudsvisit´edans chaque niveau pour lestraiter apr`es.
voidparcoursLargeur(arbreB a) {
File f=NULL;
arbreB atmp;//<-- nœud temporaire if(a!=NULL)
{
f=enfiler(a,f);
while( f!=NULL) {
atmp=defiler(&f);
printf("%d ",atmp->valeur);//<-- ici visit´e (trait´e) if(filsGauche(atmp)!=NULL)
f=enfiler(atmp->filsG,f);//<-- ici mettre en m´emoire le fils gauche if(filsDroit(atmp)!=NULL)
f=enfiler(atmp->filsD,f);//<-- ici mettre en m´emoire le fils droit }
} }
2. Arbres binaires : 2.4 Parcours d’un arbre
Parcours en largeur
Le parcours en largeur : permet d’explorer l’arbreniveau par niveau.
L’algorithme du parcours en largeurconsiste`autiliser une filepourgarder en m´emoirelesfilsdunœudsvisit´edans chaque niveau pour lestraiter apr`es.
voidparcoursLargeur(arbreB a) {
File f=NULL;
arbreB atmp;//<-- nœud temporaire if(a!=NULL)
{
f=enfiler(a,f);
while( f!=NULL) {
atmp=defiler(&f);
printf("%d ",atmp->valeur);//<-- ici visit´e (trait´e) if(filsGauche(atmp)!=NULL)
f=enfiler(atmp->filsG,f);//<-- ici mettre en m´emoire le fils gauche if(filsDroit(atmp)!=NULL)
f=enfiler(atmp->filsD,f);//<-- ici mettre en m´emoire le fils droit }
} }
2. Arbres binaires : 2.3 Fonctions de base
Fonctionquiafficheles ´el´ements d’un arbre binaire, Fonctionquitestesi unnœudsest unefeuille, Fonctionquitestesi unnœudsest unnœuds interne, Fonctionquicalculele nombre denœudsd’un arbre binaire, Fonctionquicalculele nombre denœuds internesd’un arbre binaire, Fonctionquicalculele nombre defeuillesd’un arbre binaire, Fonctionquicalculelahauteurd’un arbre binaire,
2. Arbres binaires : 2.3 Fonctions de base
Tester si un nœud est une feuille
int noeudEstFeuille(arbreB a) {
if(a==NULL) return 0;
if(a->filsD==NULL && a->filsG==NULL) return 1;
return 0;
}
2. Arbres binaires : 2.3 Fonctions de base
Tester si un nœud est une feuille
int noeudEstFeuille(arbreB a) {
if(a==NULL) return 0;
if(a->filsD==NULL && a->filsG==NULL) return 1;
return 0;
}
2. Arbres binaires : 2.3 Fonctions de base
Tester si un nœud est un nœud interne
int noeudEstInterne(arbreB a) {
return !noeudEstFeuille(a);
}
2. Arbres binaires : 2.3 Fonctions de base
Tester si un nœud est un nœud interne
int noeudEstInterne(arbreB a) {
return !noeudEstFeuille(a);
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de nœuds
int nbrNoeud(arbreB a) {
if(a==NULL) return 0;
return 1+nbrNoeud(filsDroit(a))+nbrNoeud(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de nœuds
int nbrNoeud(arbreB a) {
if(a==NULL) return 0;
return 1+nbrNoeud(filsDroit(a))+nbrNoeud(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de nœuds internes
int nbrNoeudInter(arbreB a) {
if(a==NULL) return 0;
if(noeudInterne(a)==0) return 0;
return 1+nbrNoeudInter(filsDroit(a))+nbrNoeudInter(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de nœuds internes
int nbrNoeudInter(arbreB a) {
if(a==NULL) return 0;
if(noeudInterne(a)==0) return 0;
return 1+nbrNoeudInter(filsDroit(a))+nbrNoeudInter(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de feuilles
int nbrFeuille(arbreB a) {
if(a==NULL) return 0;
if(noeudFeuille(a)==1) return 1;
return nbrFeuille(filsDroit(a))+nbrFeuille(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer le nombre de feuilles
int nbrFeuille(arbreB a) {
if(a==NULL) return 0;
if(noeudFeuille(a)==1) return 1;
return nbrFeuille(filsDroit(a))+nbrFeuille(filsGauche(a));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer la hauteur
int hauteurArbre(arbreB a) {
if(a==NULL) return 0;
return 1+max(hauteurArbre(filsDroit(a)),hauteurArbre(filsGauche(a)));
}
2. Arbres binaires : 2.3 Fonctions de base
Calculer la hauteur
int hauteurArbre(arbreB a) {
if(a==NULL) return 0;
return 1+max(hauteurArbre(filsDroit(a)),hauteurArbre(filsGauche(a)));
}
2. Arbres binaires : 2.5 Recherche dans un arbre
Larecherched’unevaleur stock´eedans un arbre est uneop´eration tr`es courantessur les arbres binaires.
Ondistingue principalement deux m´ethodes de rechercheli´ees autype de l’arbre binaireconsid´er´e.
Si l’arbre estquelconque.
Si l’arbre est unarbre de recherche.
L’objectifde la recherche est ded´eterminersi la valeurexistedans l’arbre.
Recherche dans un arbre binaire quelconque
Principe : Lafonctioncommencesa recherche `a laracine. Pour chaquenœud visit´e, si la valeur recherch´ee esttrouv´ee, la recherche esttermin´ee. Sinon, la recherchecontinuedans lesous-arbre gauche etlesous-arbre droit.
intrechercherEltArbre(arbreB a,element val) {
if(a==NULL) return0;
if(a->valeur==val) return1;
return(rechercherEltArbre(filsGauche(a), val)||rechercherEltArbre(filsDroit(a), val) );
}
2. Arbres binaires : 2.5 Recherche dans un arbre
Larecherched’unevaleur stock´eedans un arbre est uneop´eration tr`es courantessur les arbres binaires.
Ondistingue principalement deux m´ethodes de rechercheli´ees autype de l’arbre binaireconsid´er´e.
Si l’arbre estquelconque.
Si l’arbre est unarbre de recherche.
L’objectifde la recherche est ded´eterminersi la valeurexistedans l’arbre.
Recherche dans un arbre binaire quelconque
Principe : Lafonctioncommencesa recherche `a laracine. Pour chaquenœud visit´e, si la valeur recherch´ee esttrouv´ee, la recherche esttermin´ee. Sinon, la recherchecontinuedans lesous-arbre gauche etlesous-arbre droit.
intrechercherEltArbre(arbreB a,element val) {
if(a==NULL) return0;
if(a->valeur==val) return1;
return(rechercherEltArbre(filsGauche(a), val)||rechercherEltArbre(filsDroit(a), val) );
}
2. Arbres binaires : 2.5 Recherche dans un arbre
Recherche dans un arbre binaire de recherche
Contrairement`a la recherche dans unarbre quelconqueo`u il faut parcourir quasiment tous les nœudsde l’arbre pourd´eterminersil’´el´ement existe, larecherchedans unarbre binaire de recherchepermet de parcourirseulement une branchede l’arbre.
Principe : Lafonctioncommencesa recherche `a laracine. Pour chaquenœud visit´e, si la valeur recherch´ee esttrouv´ee, la recherche esttermin´ee. Sinon, la recherchecontinuedans lesous-arbre gauche oulesous-arbre droit.
intrechercherEltArbreRech(arbreB a,element val) {
if(a==NULL) return0;
if(a->valeur==val) return1;
if(a->valeur>=val)
returnrechercherEltArbreRech(filsGauche(a), val);
returnrechercherEltArbreRech(filsDroit(a), val) }
2. Arbres binaires : 2.5 Recherche dans un arbre
Recherche dans un arbre binaire de recherche
Contrairement`a la recherche dans unarbre quelconqueo`u il faut parcourir quasiment tous les nœudsde l’arbre pourd´eterminersil’´el´ement existe, larecherchedans unarbre binaire de recherchepermet de parcourirseulement une branchede l’arbre.
Principe : Lafonctioncommencesa recherche `a laracine. Pour chaquenœud visit´e, si la valeur recherch´ee esttrouv´ee, la recherche esttermin´ee. Sinon, la recherchecontinuedans lesous-arbre gauche oulesous-arbre droit.
intrechercherEltArbreRech(arbreB a,element val) {
if(a==NULL) return0;
if(a->valeur==val) return1;
if(a->valeur>=val)
returnrechercherEltArbreRech(filsGauche(a), val);
returnrechercherEltArbreRech(filsDroit(a), val) }
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Lasuppressiond’une valeur (ou un nœud) dans un arbre est uneop´eration plus complexe.
En effet,supprimer un ´el´ementdans un arbre revient `ad´etruirelenœud contenant cet ´el´ement.
Cependant, unnœudayant des fils s’il est supprim´e,entraˆıneuner´eorganisation de l’arbre.
Autrement,que fairealors dessous-arbresdu nœud `asupprimer? La r´eponsed´ependdutypede l’arbre trait´e.
Si l’arbre consid´er´e est unarbre binaire de recherche, on peutsupprimer un nœud tout en gardantl’aspectde cet arbre, c-`a-d garderl’organisation de l’arbre selon leconceptdesarbres binaires de recherche.
Si l’arbre consid´er´e est unarbre binaire quelconque, on peutsupprimerle nœud et sessous-arbresousupprimerseulement le nœud
.
Dans la suite, nous allonspr´esenterunefonctionqui permet desupprimerun nœud dans unarbre binaire de recherchesans supprimerses fils.
Une autrefonctionqui permet ded´etruire compl`etementun nœud et ses descendants.
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Suppression d’un ´ el´ ement dans un arbre binaire de recherche
Principe : Sinest le nœud qui contient l’´el´ement `asupprimer, alorstrois cas sont envisageables :
Sinest unefeuille, alors on lesupprime.
Sinest unnœud ayant un seul fils, alors onsupprimenet on leremplace par ce fils.
Sinest unnœud ayant deux fils(gauche et droit), alors oncherchedans lesous-arbre gauchela feuillexqui porte leplus grand ´el´ement. Ensuite, onremplacelecontenudenpar lecontenudex, et onsupprimex.
Trois fonctionscoop`erentpour r´ealiser cettetˆache:
une fonction permet desupprimer la racined’un nœud.
une fonction permet ded´eterminer le maximumdes ´el´ements d’un arbre binaire de recherche.
une fonction permet desupprimer un ´el´ementdans un arbre binaire de recherche.
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Exemple 1 : Suppression d’une feuille
20 16 12 11 13
17 16 19
23 22 21
27
= ⇒
20 16 12 11 13
17 16 19
23
22 27
Exemple 2 : Suppression d’un nœud `a deux fils
20 16 12 11 13
17 16 19
23 22 21
27
= ⇒
20 13 12 11
17 16 19
23
22 27
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Maximum d’un arbre binaire de recherche arbreBMaxArbreRech(arbreB a)
{
if(a->filsD == NULL) returna;
returnMaxArbreRech(a->filsD);
}
Supprimer la racine d’un nœud arbreBsupprimerRacine(arbreB a)
{
arbreB tmp;
arbreB supprimerElt((int v, arbreB a);
if(a->filsG == NULL) returna->filsD;
if(a->filsD == NULL) returna->filsG;
tmp = MaxArbreRech(a->filsG);
a->valeur= tmp->valeur;
a->filsG = supprimerElt((tmp->valeur, a->filsG);
returna;
}
Supprimer la valeur d’un nœud arbreBsupprimerElt(int v, arbreB a)
{
if(a== NULL) returna;
if(v == a->valeur) returnsupprimerRacine(a);
if(v < a->valeur)
a->filsG = supprimerElt(v, a->filsG);
else
a->filsD = supprimerElt(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Maximum d’un arbre binaire de recherche arbreBMaxArbreRech(arbreB a)
{
if(a->filsD == NULL) returna;
returnMaxArbreRech(a->filsD);
}
Supprimer la racine d’un nœud arbreBsupprimerRacine(arbreB a)
{
arbreB tmp;
arbreB supprimerElt((int v, arbreB a);
if(a->filsG == NULL) returna->filsD;
if(a->filsD == NULL) returna->filsG;
tmp = MaxArbreRech(a->filsG);
a->valeur= tmp->valeur;
a->filsG = supprimerElt((tmp->valeur, a->filsG);
returna;
}
Supprimer la valeur d’un nœud arbreBsupprimerElt(int v, arbreB a)
{
if(a== NULL) returna;
if(v == a->valeur) returnsupprimerRacine(a);
if(v < a->valeur)
a->filsG = supprimerElt(v, a->filsG);
else
a->filsD = supprimerElt(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Maximum d’un arbre binaire de recherche arbreBMaxArbreRech(arbreB a)
{
if(a->filsD == NULL) returna;
returnMaxArbreRech(a->filsD);
}
Supprimer la racine d’un nœud arbreBsupprimerRacine(arbreB a)
{
arbreB tmp;
arbreB supprimerElt((int v, arbreB a);
if(a->filsG == NULL) returna->filsD;
if(a->filsD == NULL) returna->filsG;
tmp = MaxArbreRech(a->filsG);
a->valeur= tmp->valeur;
a->filsG = supprimerElt((tmp->valeur, a->filsG);
returna;
}
Supprimer la valeur d’un nœud arbreBsupprimerElt(int v, arbreB a)
{
if(a== NULL) returna;
if(v == a->valeur) returnsupprimerRacine(a);
if(v < a->valeur)
a->filsG = supprimerElt(v, a->filsG);
else
a->filsD = supprimerElt(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Maximum d’un arbre binaire de recherche arbreBMaxArbreRech(arbreB a)
{
if(a->filsD == NULL) returna;
returnMaxArbreRech(a->filsD);
}
Supprimer la racine d’un nœud arbreBsupprimerRacine(arbreB a)
{
arbreB tmp;
arbreB supprimerElt((int v, arbreB a);
if(a->filsG == NULL) returna->filsD;
if(a->filsD == NULL) returna->filsG;
tmp = MaxArbreRech(a->filsG);
a->valeur= tmp->valeur;
a->filsG = supprimerElt((tmp->valeur, a->filsG);
returna;
}
Supprimer la valeur d’un nœud arbreBsupprimerElt(int v, arbreB a)
{
if(a== NULL) returna;
if(v == a->valeur) returnsupprimerRacine(a);
if(v < a->valeur)
a->filsG = supprimerElt(v, a->filsG);
else
a->filsD = supprimerElt(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Suppression d’un ´ el´ ement dans un arbre binaire quelconque
Principe : Sinest le nœud qui contient l’´el´ement `asupprimer, alors on supprime compl`etementl’arbre deracinen.
L’id´eeest desupprimerlesfeuilles une par unes. Onr´eit`erel’op´eration autant de fois qu’il y a de feuilles.
Exemple : 3 16 18
1 3
10 12 20
25 1 11
29
= ⇒
3 16 18
1 3
25 1 11
29
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Vider un arbre arbreBviderArbreB(arbreB a)
{
arbreB aG;
arbreB aD;
if(a!= NULL) {
aG = a->filsG;
aD = a->filsD;
a->filsG=viderArbreB(aG);
a->filsD=viderArbreB(aD);
free(a);
a=NULL;
returna;
} returnNULL;
}
Supprimer un nœud arbreBsupprimerNoeudQcq(int v, arbreB a)
{
arbreB tmp;
if(a== NULL) returna;
if(v == a->valeur) {
tmp=a;
returnviderArbreB(tmp);
}
if(rechercherArbre(filsGauche(a), v)) a->filsG = supprimerNoeudQcq(v, a->filsG);
else
a->filsD = supprimerNoeudQcq(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Vider un arbre arbreBviderArbreB(arbreB a)
{
arbreB aG;
arbreB aD;
if(a!= NULL) {
aG = a->filsG;
aD = a->filsD;
a->filsG=viderArbreB(aG);
a->filsD=viderArbreB(aD);
free(a);
a=NULL;
returna;
} returnNULL;
}
Supprimer un nœud arbreBsupprimerNoeudQcq(int v, arbreB a)
{
arbreB tmp;
if(a== NULL) returna;
if(v == a->valeur) {
tmp=a;
returnviderArbreB(tmp);
}
if(rechercherArbre(filsGauche(a), v)) a->filsG = supprimerNoeudQcq(v, a->filsG);
else
a->filsD = supprimerNoeudQcq(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Vider un arbre arbreBviderArbreB(arbreB a)
{
arbreB aG;
arbreB aD;
if(a!= NULL) {
aG = a->filsG;
aD = a->filsD;
a->filsG=viderArbreB(aG);
a->filsD=viderArbreB(aD);
free(a);
a=NULL;
returna;
} returnNULL;
}
Supprimer un nœud arbreBsupprimerNoeudQcq(int v, arbreB a)
{
arbreB tmp;
if(a== NULL) returna;
if(v == a->valeur) {
tmp=a;
returnviderArbreB(tmp);
}
if(rechercherArbre(filsGauche(a), v)) a->filsG = supprimerNoeudQcq(v, a->filsG);
else
a->filsD = supprimerNoeudQcq(v, a->filsD);
returna;
}
2. Arbres binaires : 2.6 Suppression d’un ´ el´ ement dans arbre binaire
Code en C
Vider un arbre arbreBviderArbreB(arbreB a)
{
arbreB aG;
arbreB aD;
if(a!= NULL) {
aG = a->filsG;
aD = a->filsD;
a->filsG=viderArbreB(aG);
a->filsD=viderArbreB(aD);
free(a);
a=NULL;
returna;
} returnNULL;
}
Supprimer un nœud arbreBsupprimerNoeudQcq(int v, arbreB a)
{
arbreB tmp;
if(a== NULL) returna;
if(v == a->valeur) {
tmp=a;
returnviderArbreB(tmp);
}
if(rechercherArbre(filsGauche(a), v)) a->filsG = supprimerNoeudQcq(v, a->filsG);
else
a->filsD = supprimerNoeudQcq(v, a->filsD);
returna;
}
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Motivation et Pr´esentation
Nous avons vu que lesop´erations d’insertion ou de suppressiondes ´el´ements dans unarbre binaire de recherchepeut donner des arbres totalement d´es´equilibr´es,
autrement, ladiff´erence entre la hauteur des sous-arbres est assez importante. Il peut y avoir des arbres dont laprofondeur est proche leur taille.
Ceci peutinfluencer le coˆut en tempsdes traitements sur ce type d’arbre.
Pour´eviterce genre d’arbres, on peut chercher `agarderunarbre binaire de recherchesous uneforme ´equilibr´eeapr`es chaqueop´eration d’insertion ou de suppression.
En algorithmique, il existe plusieurstypes d’arbresdits´equilibr´eslesarbres AVL, lesarbres rouge et noir, lesarbres a-b.
Dans la suite, noustraitonsle cas desarbres AVL(notion introduite en 1962 par deux russes Adelson-Velskii et Landis).
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
D´efinition
Unarbre binaire de rechercheest unarbre AVLsi, pour tout nœud de l’arbre, les hauteurs des sous-arbres gaucheetdroitdiff`erent d’au plus 1.
Exemple :
18
16
12
11 13
17
16 17
23
22
21
27
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Insertion et suppression
L’insertion (ou la suppression)dans unarbre AVLse faitcommedans unarbre de recherchesauf qu’il fautmaintenir l’´equilibrede l’arbre.
Pour cela, lors del’insertion (ou suppression), s’il peut y avoir und´es´equilibre trop important (≥2)entre lesdeux sous-arbres du nœud trait´eil fautcr´eer un
´
equilibrepar desrotations (gauche ou droite).
Les op´erations de rotationtransforment la configurationdes sous-arbres de gauche ou de droitsans modifierl’ordre sym´etrique des nœuds (l’ordre dans le parcours infixe).
La rotationpr´eserve la propri´et´ed’arbre binaire de recherche, en revanche elle peutdiminuer la hauteurdu sous-arbre.
Rotation :Les rotations sontillustr´eespar lafiguresuivante :
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Op´erations sur les arbres AVL :
Equilibrer :´ si lahauteur des sous-arbres droit et gauchediff`ere d’au plus de 1, effectuer unerotation gaucheoudroiteou lesdeuxselon la situation.
Insertion : onajouteun ´el´ement `al’arbre AVLd’unemani`ere similaire`a un arbre binaire de recherchesauf qu’il faut pr´eserver l’´equilibre`a chaque insertion.
Suppression : onsupprimeun ´el´ement del’arbre AVLd’unemani`ere similaire`a un arbre binaire de recherche sauf qu’il faut pr´eserver l’´equilibre`a chaque suppression.
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Exemple 1 :Ajout l’´el´ement 11
20 16
12 17
23
−−−−−→
Insertion
20 16 12 11
17
23 −−−−−−−→ RotationD
16 12 11
20
17 23
Exemple 2 :Ajout l’´el´ement 18
20 16
12 17
23
−−−−→
Insertion
20 16
12 17
23
−−−−−−−−−−→ RotationG en16
20 17
16 18
23 −RotationD−−−−−→
17 16 12
20
18 23
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Exemple 1 : suppression l’´el´ement 22
20 16 12 11
17 23
22
−−−−−−−−→ Suppression
20 16 12 11
17
23 −−−−−−−→ RotationD
16 12 11
20
17 23
Exemple 2 : Suppression l’´el´ement 25
20 16
12 17
18 23
25
−−−−−−→
Suppression
20 16
12 17
18 23
−−−−−−−−−−→ RotationG en16
20 17 16 12
18
23 −RotationD−−−−−→
17 16 12
20
18 23
2. Arbres binaires : Arbres binaires ´ equilibr´ es AVL
Implantation d’un arbre AVL en C :
Pourimplanter en langage Cles op´erations d’insertionet desuppressiondes ´el´ements dans unarbres AVL, il faut ´ecrire desfonctionsqui permettent
1 d’effectuer unerotation gauchesur unarbre binaire de recherche,
2 d’effectuer unerotation droitesur unarbre binaire de recherche,
3 d’´equilibrerunarbre binaire de recherche,
4 d’ajouterun ´el´ement dans unarbre binaire AVL,
5 desupprimerun ´el´ement dans unarbre binaire AVL, Ces fonctions seront r´ealis´ees en TD.