TD05 ABR Correction
Exercice 1
Exercice 2
- On définit une structure représentant un nœud dans un arbre binaire
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
typedef struct arbre_struct
{
int value; // La valeur contenue dans le nœud
struct arbre_struct *fd; // Pointeur vers le sous-arbre droit
struct arbre_struct *fg; // Pointeur vers le sous-arbre gauche
} Arbre;
typedef Arbre *pArbre;
- On crée la fonction pour créer un nouveau nœud dans l’arbre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pArbre creeArbre(int e)
{
// Allocation dynamique d'un nouveau nœud
pArbre new = malloc(sizeof(Arbre));
if (new == NULL)
{ // Vérification si l'allocation a échoué
exit(EXIT_FAILURE); // Arrêt du programme en cas d'échec
}
// Initialisation du nœud avec la valeur donnée et des sous-arbres vides
new->value = e;
new->fd = NULL;
new->fg = NULL;
return new; // Retourne le nouveau nœud
}
- On crée la fonction pour rechercher une valeur dans un arbre binaire
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int recherche(pArbre a, int e)
{
if (a == NULL)
{ // Si l'arbre est vide, la valeur n'existe pas
return 0;
}
if (a->value == e)
{ // Si la valeur est trouvée, retourner 1
return 1;
}
if (e < a->value)
{ // Si la valeur recherchée est plus petite, explorer le sous-arbre gauche
return recherche(a->fg, e);
}
// Sinon, explorer le sous-arbre droit
return recherche(a->fd, e);
}
- On crée la fonction pour insérer une valeur dans un arbre binaire de recherche (récursive)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pArbre insertionABR(pArbre a, int e)
{
if (a == NULL)
{ // Si l'arbre est vide, créer un nouveau nœud
return creeArbre(e);
}
if (e < a->value)
{ // Si la valeur est plus petite, insérer dans le sous-arbre gauche
a->fg = insertionABR(a->fg, e);
}
else
{ // Sinon, insérer dans le sous-arbre droit
a->fd = insertionABR(a->fd, e);
}
return a; // Retourner l'arbre modifié
}
- On crée la fonction pour insérer une valeur dans un arbre binaire de recherche (itérative)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
pArbre insertionABR_iter(pArbre a, int e)
{
if (a == NULL)
{ // Si l'arbre est vide, créer un nouveau nœud
return creeArbre(e);
}
pArbre actual = a; // Initialisation d'un pointeur pour parcourir l'arbre
while (actual != NULL)
{ // Boucle pour trouver la bonne position d'insertion
if (e < actual->value)
{ // Explorer le sous-arbre gauche
if (actual->fg == NULL)
{ // Si le sous-arbre gauche est vide, insérer ici
actual->fg = creeArbre(e);
break;
}
else
{
actual = actual->fg;
}
}
else
{ // Explorer le sous-arbre droit
if (actual->fd == NULL)
{ // Si le sous-arbre droit est vide, insérer ici
actual->fd = creeArbre(e);
break;
}
else
{
actual = actual->fd;
}
}
}
return a; // Retourner l'arbre modifié
}
- On crée la fonction pour supprimer le plus grand élément dans un sous-arbre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pArbre suppMax(pArbre a, int *pe)
{
pArbre tmp;
if (a->fd != NULL)
{ // Si le sous-arbre droit existe, continuer à descendre
a->fd = suppMax(a->fd, pe);
}
else
{ // Si le nœud courant est le plus grand
*pe = a->value; // Stocker la valeur du nœud
tmp = a; // Sauvegarder l'adresse du nœud à libérer
a = a->fg; // Remonter le sous-arbre gauche
free(tmp); // Libérer la mémoire du nœud supprimé
}
return a; // Retourner le sous-arbre modifié
}
- On crée la fonction pour supprimer une valeur dans un arbre binaire de recherche
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
pArbre supprimerABR(pArbre a, int e)
{
pArbre tmp;
if (a == NULL)
{ // Si l'arbre est vide, rien à supprimer
return a;
}
if (e < a->value)
{ // Explorer le sous-arbre gauche si la valeur est plus petite
a->fg = supprimerABR(a->fg, e);
}
else if (e > a->value)
{ // Explorer le sous-arbre droit si la valeur est plus grande
a->fd = supprimerABR(a->fd, e);
}
else
{ // Si la valeur est trouvée
if (a->fg == NULL)
{ // Si le sous-arbre gauche est vide
tmp = a;
a = a->fd; // Remonter le sous-arbre droit
free(tmp); // Libérer la mémoire du nœud supprimé
}
else
{ // Si le sous-arbre gauche existe
a->fg = suppMax(a->fg, &a->value); // Remplacer avec le plus grand élément du sous-arbre gauche
}
}
return a; // Retourner l'arbre modifié
}
Exercice 3
Exercice 4
- On définit d’une structure représentant un nœud d’un arbre binaire
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <stdlib.h>
typedef struct arbre_struct {
int value; // La valeur contenue dans le nœud
struct arbre_struct *fd; // Pointeur vers le sous-arbre droit
struct arbre_struct *fg; // Pointeur vers le sous-arbre gauche
} Arbre;
typedef Arbre* pArbre;
- On crée la fonction pour créer un nouveau nœud dans l’arbre
1
2
3
4
5
6
7
8
9
10
11
12
13
pArbre creeArbre(int e) {
// Allocation dynamique pour un nouveau nœud
pArbre new = malloc(sizeof(Arbre));
if (new == NULL) { // Vérification de l'échec de l'allocation
exit(EXIT_FAILURE); // Arrêt immédiat en cas d'erreur
}
// Initialisation du nœud avec la valeur donnée et des sous-arbres vides
new->value = e;
new->fd = NULL;
new->fg = NULL;
return new; // Retourne le nouveau nœud
}
- On crée la fonction récursive pour vérifier si un sous-arbre droit respecte la propriété de l’ABR, Chaque nœud dans le sous-arbre droit doit être strictement supérieur à une valeur minimale
min
1
2
3
4
5
6
7
8
int verifierDroit(Arbre *a, int min) {
if (a == NULL) { // Si le sous-arbre est vide, il respecte la propriété
return 1;
}
// Vérifie si le nœud courant respecte la propriété et applique la vérification récursive
return (a->value > min) && verifierDroit(a->fg, min) && verifierDroit(a->fd, min);
}
- On crée la fonction récursive pour vérifier si un sous-arbre gauche respecte la propriété de l’ABR, Chaque nœud dans le sous-arbre gauche doit être strictement inférieur à une valeur maximale
max
1
2
3
4
5
6
7
8
int verifierGauche(Arbre *a, int max) {
if (a == NULL) { // Si le sous-arbre est vide, il respecte la propriété
return 1;
}
// Vérifie si le nœud courant respecte la propriété et applique la vérification récursive
return (a->value < max) && verifierGauche(a->fg, max) && verifierGauche(a->fd, max);
}
- On crée la fonction principale pour vérifier si un arbre est un ABR (Arbre Binaire de Recherche)
1
2
3
4
5
6
7
8
9
10
11
12
int estABR(pArbre a) {
if (a == NULL) { // Si l'arbre est vide, c'est un ABR valide
return 1;
}
// Vérifie si les sous-arbres gauche et droit respectent les propriétés de l'ABR
if (!verifierGauche(a->fg, a->value) || !verifierDroit(a->fd, a->value)) {
return 0; // Si une des propriétés est violée, ce n'est pas un ABR
}
// Vérifie récursivement les sous-arbres
return estABR(a->fg) && estABR(a->fd);
}
Exercice 5
Exercice 6
Le contenu de cet article est la propriété exclusive de son auteur.