Vous êtes sur la page 1sur 12

Programmation avancée

Arbres binaires de recherche

EL Moukhtar ZEMMOURI
ENSAM – Meknès
Version – 1.0

Définitions

E. Zemmouri, ENSAM - Meknès 2


Arbre binaire de recherche

• Arbre binaire de recherche (ABR)


• Ou arbre binaire ordonné 10

• Un arbre binaire de recherche est


4 13
o Soit vide
o Soit formé d’un nœud racine dont les deux sous 2 7 17
arbres gauche et droit sont des arbres binaires de
recherche et l’étiquette (clé ou valeur) à la racine
6 8 15
est :
• supérieure (ou égale !) à toutes les étiquettes
des nœuds du sous-arbre gauche
• inférieure à toutes les étiquettes des nœuds
du sous-arbre droit.

E. Zemmouri, ENSAM - Meknès 3

Exemples

10 17 7

13
4 13 4 13

10
2 7 17 2 10 17

10
2

4 13

2 7 17

E. Zemmouri, ENSAM - Meknès 4


Exercice

• Ecrire une fonction pour vérifier si un arbre


binaire donné en argument est un ABR ou non.

Algorithme Fonction C++

Fonction estABR (racine) /**


si racine est null alors * Fonction pour verifier si un arbre binaire est un ABR
retourner vrai */
sinon bool estABR (Noeud * racine){
si estABR(racine->fg) et estABR(racine->fd) alors if (racine == NULL) return true;
si racine->valeur > max(racine->fg) et if (estABR(racine->fg) && estABR(racine->fd)){
racine->valeur < min(racine->fd) alors if (racine->valeur > maxAB(racine->fg) &&
retourner vrai racine->valeur < minAB(racine->fd)){
finsi return true;
finsi }
retourner faux }
finsi return false;
fin }

E. Zemmouri, ENSAM - Meknès 5

Exercice
• Les deux fonctions min et max d’un arbre binaire (pas nécessairement ABR)

Fonction C++ Min arbre binaire Fonction C++ Max arbre binaire

/** /**
* Fonction qui retourne la valeur min d'un arbre binaire * Fonction qui retourne la valeur max d'un arbre binaire
* non vide (l'arbre n'est pas forcement un ABR) * non vide (l'arbre n'est pas forcement un ABR)
*/ */
int minAB (Noeud * racine){ int maxAB (Noeud * racine){
int m = racine->valeur; int m = racine->valeur;
if (racine->fg != NULL){ if (racine->fg != NULL){
int a = minAB (racine->fg); int a = maxAB (racine->fg);
if (a < m) m = a; if (a > m) m = a;
} }
if (racine->fd != NULL){ if (racine->fd != NULL){
int b = minAB (racine->fd); int b = maxAB (racine->fd);
if (b < m) m = b; if (b > m) m = b;
} }
return m; return m;
} }

E. Zemmouri, ENSAM - Meknès 6


Propriétés d’un ABR

• Un parcours infixé gauche puis droit d’un ABR permet de traiter les
éléments de l’arbre dans l’ordre croissant.
• La recherche d’un élément est facile est rapide :
o Se fait en O(ℎ) , avec ℎ la hauteur de l’ARB

• L’insertion est simple et se fait toujours au niveau d’une feuille


• La suppression d’une feuille est simple
• La suppression d’un nœud interne nécessite la réorganisation de l’ABR.
o Un peu compliquée !

E. Zemmouri, ENSAM - Meknès 7

Recherche, insertion et suppression

E. Zemmouri, ENSAM - Meknès 8


Rappel des déclarations de types

• On suppose un arbre binaire d’éléments de type int :

typedef struct noeud {


int valeur;
struct noeud * fg;
struct noeud * fd;
} Noeud;

E. Zemmouri, ENSAM - Meknès 9

Recherche dans un ABR

• Fonction pour chercher un élément dans un ABR.


• Retourne un pointeur sur le nœud contenant l’élément ou NULL.

Fonction C++ récursive


Algorithme
/**
Fonction chercher (racine, val) * Fonction recursive de recherche dans un ABR
si racine est NULL alors * retourne un pointeur sur le noeud contenant val
retourner NULL * ou NULL
sinon si racine->valeur == val alors */
retourner racine Noeud * chercher (Noeud * racine, int val){
sinon si val < racine->valeur alors if (racine == NULL) return NULL
retourner chercher (racine->fg, val) if (racine->valeur == val) return racine;
sinon if (val < racine->valeur)
retourner chercher (racine->fd, val) return chercher (racine->fg, val);
finsi return chercher (racine->fd, val);
fin }

E. Zemmouri, ENSAM - Meknès 10


Recherche dans un ABR

• Version itérative de la fonction de recherche :

Fonction C++ itérative

/**
* Fonction Iterative de recherche dans un ABR
* retourne un pointeur sur le noeud contenant val
* ou NULL
*/
Noeud * chercher_iterative (Noeud * racine, int val){
while (racine != NULL){
if (racine->valeur == val) return racine;
if (val < racine->valeur) racine = racine->fg;
else racine = racine->fd;
}
return NULL;
}

E. Zemmouri, ENSAM - Meknès 11

Va l e u r m i n d ’ u n A B R

• Fonction pour chercher la valeur minimum d’un ABR.


• Retourne un pointeur sur le nœud contenant la valeur min ou NULL.
o Il suffit de suivre le chemin le plus à gauche dans l’arbre.

Fonction C++ itérative


Fonction C++ récursive /**
/** * Fonction Iterative de recherche du min dans un ABR
* Fonction recursive de recherche du min dans un ABR * retourne un pointeur sur le noeud contenant le min
* retourne un pointeur sur le noeud contenant le min * ou NULL si l'arbre est vide
* ou NULL si l'arbre est vide */
*/ Noeud * minABR_iter (Noeud * racine){
Noeud * minABR (Noeud * racine){ if (racine == NULL) return NULL;
if (racine == NULL) return NULL; while (racine->fg != NULL)
if (racine->fg == NULL) return racine; racine = racine->fg;
else return minABR (racine->fg); return racine;
} }

E. Zemmouri, ENSAM - Meknès 12


Va l e u r m a x d ’ u n A B R

• Fonction pour chercher la valeur maximum d’un ABR.


• Retourne un pointeur sur le nœud contenant la valeur max ou NULL.
o Il suffit de suivre le chemin le plus à droite dans l’arbre.

Fonction C++ itérative


Fonction C++ récursive /**
/** * Fonction Iterative de recherche du max dans un ABR
* Fonction recursive de recherche du max dans un ABR * retourne un pointeur sur le noeud contenant le max
* retourne un pointeur sur le noeud contenant le max * ou NULL si l'arbre est vide
* ou NULL si l'arbre est vide */
*/ Noeud * maxABR_iter (Noeud * racine){
Noeud * maxABR (Noeud * racine){ if (racine == NULL) return NULL;
if (racine == NULL) return NULL; while (racine->fd != NULL)
if (racine->fd == NULL) return racine; racine = racine->fd;
else return maxABR (racine->fd); return racine;
} }

E. Zemmouri, ENSAM - Meknès 13

Insertion dans un ABR


• Fonction pour insérer un nouveau élément dans un ABR. N.B. nécessite un pointeur double sur
la racine pour l’implémentation C++ !
• L’insertion se fait au niveau d’une feuille.
Fonction C++ récursive

void inserer (Noeud ** racine, int val){


Algorithme
if ( *racine == NULL ){
Fonction inserer (racine, val)
Noeud * p = new Noeud;
si racine est NULL alors
p->valeur = val;
noeud = creer_noeud (val, NULL, NULL)
p->fg = NULL;
racine = noeud
p->fd = NULL;
sinon
*racine = p;
si val < racine->valeur alors
}
inserer (racine->fg, val)
else {
sinon si val > racine->valeur alors
if ( val < (*racine)->valeur )
inserer (racine->fd, val)
inserer( &((*racine)->fg) , val);
sinon
else if ( (*racine)->valeur < val )
Ecrire ("la valeur existe déjà")
inserer( &((*racine)->fd) , val);
finsi
else
finsi
cout << val << " exist deja dans l'arbre \n";
fin
}
}
E. Zemmouri, ENSAM - Meknès 14
Insertion dans un ABR
• Version itérative de la fonction d’insertion :
Fonction C++ itérative

/**
* Fonction Iterative pour inserer une nouvelle valeur dans un ABR
*/
void inserer_iterative (Noeud ** racine, int val){
while ( *racine != NULL ) {
if ( val < (*racine)->valeur ) racine = &((*racine)->fg);
else if ( (*racine)->valeur < val ) racine = &((*racine)->fd);
else {
cout << val << " exist deja dans l'arbre \n";
return ;
}
}
Noeud * p = new Noeud;
p->valeur = val;
p->fg = NULL;
p->fd = NULL;
*racine = p;

E. Zemmouri, ENSAM - Meknès } 15

Insertion dans un ABR

• La structure de l’arbre obtenu dépend de l’ordre d’insertion des éléments.


o è Les ABR ne sont pas forcément équilibrés !
• Exemple :

10 17 7

13
4 13 4 13

10
2 7 17 2 10 17

E. Zemmouri, ENSAM - Meknès 16


Suppression dans un ABR

• 1er Cas :
o Si le nœud à supprimer est une feuille (SAG et SAD sont vides),
o On supprime simplement ce nœud.

• Exemple : suppression de 9

10 10

4 17 4 17

7 14 7 14

5 9 13 16 5 9 13 16

E. Zemmouri, ENSAM - Meknès 17

Suppression dans un ABR

• 2ième Cas :
o Si le SAD du nœud à supprimer est vide, il suffit de modifier le pointeur du père et de le
faire pointer sur le SAG du nœud à supprimer.

• Exemple : suppression de 17

10 10

4 17 4 17

7 14 7 14

5 9 13 16 5 9 13 16

E. Zemmouri, ENSAM - Meknès 18


Suppression dans un ABR

• 3ième Cas :
o Si le SAG du nœud à supprimer est vide, il suffit de modifier le pointeur du père et de le
faire pointer sur le SAD du nœud à supprimer.

• Exemple : suppression de 4

10 10

4 17 4 17

7 14 7 14

5 9 13 16 5 9 13 16

E. Zemmouri, ENSAM - Meknès 19

Suppression dans un ABR

• 4ième Cas :
o Le SAG et le SAD ne sont pas NULL. La valeur à supprimer est remplacée dans le nœud
par la valeur la plus grande du SAG (ou la valeur la plus petite du SAD). Le nœud
contenant cette valeur est supprimé.

• Exemple : suppression de 10

10 9

4 17 4 17

7 14 7 14

5 9 13 16 5 9 13 16

E. Zemmouri, ENSAM - Meknès 20


Suppression dans un ABR
Algorithme CAS 1

Fonction supprimer (racine, val) delete racine


si racine n’est pas null alors racine = NULL
si val == racine->valeur alors
si racine->fg est null et racine->fd est null alors CAS 2
CAS 1
Noeud p = racine
sinon si racine->fd est null alors
racine = racine->fg
CAS 2
delete p
sinon si racine->fg est null alors
CAS 3
CAS 3
sinon
CAS 4 Noeud p = racine

finsi racine = racine->fd

sinon si val < racine->valeur alors delete p

supprimer (racine->fg, val)


sinon CAS 4

supprimer (racine->fd, val) Noeud * p = max (racine->fg)


finsi racine->valeur = p->valeur
finsi delete p;
fin p = NULL;

E. Zemmouri, ENSAM - Meknès 21

Fonction C++ récursive Suppression dans un ABR


/**
* Fonction Recursive pour supprimer une valeur d'un ABR Fonction C++ itérative
*/ /**
void supprimer_recursive (Noeud ** racine, int val){ * Fonction Iterative pour supprimer une valeur d'un ABR
if ( *racine != NULL ){ */
if ( (*racine)->valeur == val ){
void supprimer_iterative (Noeud ** racine, int val){
if ( (*racine)->fg == NULL && (*racine)->fd == NULL ){
while ( *racine != NULL && (*racine)->valeur != val ) {
delete *racine;
*racine = NULL; if ( val < (*racine)->valeur ) racine = &((*racine)->fg);
} else racine = &((*racine)->fd);
else if ( (*racine)->fd == NULL ){ }
Noeud * p = *racine; if ( *racine != NULL ){
*racine = (*racine)->fg; if ( (*racine)->fg == NULL && (*racine)->fd == NULL ){
delete p; delete *racine;
} *racine = NULL;
else if ( (*racine)->fg == NULL ){
}
Noeud * p = *racine;
*racine = (*racine)->fd; else if ( (*racine)->fd == NULL ){
delete p; Noeud * p = *racine;
} *racine = (*racine)->fg;
else { delete p;
Noeud ** p = &((*racine)->fg); }
while ( (*p)->fd != NULL) p = &((*p)->fd); else if ( (*racine)->fg == NULL ){
(*racine)->valeur = (*p)->valeur;
Noeud * p = *racine;
delete *p;
*racine = (*racine)->fd;
*p = NULL;
} delete p;
} }
else if ( val < (*racine)->valeur ){ else {
supprimer_recursive (&((*racine)->fg) , val) Noeud ** p = &((*racine)->fg);
} while ( (*p)->fd != NULL) p = &((*p)->fd);
else { (*racine)->valeur = (*p)->valeur;
supprimer_recursive (&((*racine)->fd) , val) delete *p;
}
*p = NULL;
}
} }
}
E. Zemmouri, ENSAM - Meknès } 22
Programmation avancée

Arbres binaires de recherche

EL Moukhtar ZEMMOURI
ENSAM – Meknès
Version – 1.0

Vous aimerez peut-être aussi