Vous êtes sur la page 1sur 212

Département d’Informatique

Parcours MIP (S3)

Module I133 :
Structures de données
- cours -
Version : Octobre 2022
Badr HSSINA - Enseignant chercheur
b a d r. h s s i n a @ u n i v h 2 c . m a
Laboratoire d’Intelligence Machine ( LIM)
FST Mohammedia, Université Hassan II de Casablanca

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 1


www.hssinabadr.com

Support de cours + Travaux dirigés + Travaux


pratiques sont disponibles sur le site ci-dessus.

Prof: Badr HSSINA FST MOHAMMEDIA 2


Plan Global du module
Rappel + Allocation mémoire
Structures linéaires
 Listes simplement chaînées
 Listes doublement chaînées
 Piles
 Files
Structures non linéaires
 Arbres

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 3


Rappel : Le type structure

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 4


Introduction
 Les tableaux permettent de désigner sous un seul nom un ensemble
de valeurs de même type, chacune repérée par un indice.
 Les structures permettent de désigner sous un seul nom un ensemble
de valeurs pouvant être de types différents;
 Le type structure (struct) en C est une collection de champs qui
peuvent être de types différents.
 Exemple : Supposons qu'on désire déclarer deux variables pers1 et
pers2 de type structure et que chaque personne dispose de quatre
informations.
 numéro : un entier
 taille et poids : deux réels
 sexe : un caractère.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 5


Déclarer une structure
1. Déclaration directe sans le nom du type structure.

struct
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 6


Déclarer une structure
2. Déclaration directe avec le nom du type structure.
 On déclare d'abord le type :
struct personne
{ int numero ;
float taille, poids ;
char sexe ;
} ;
 On déclare après les variables : struct personne pers1, pers2 ;
 Pour déclarer d'autres variables de ce type, il suffit de se référer au type
"struct personne " .

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 7


Déclarer une structure
3. Déclarer en même temps le nom du type et les
variables

struct personne
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 8


Déclarer une structure
4. Déclaration en utilisant « typedef »

typedef struct {
int numero ;
float taille, poids ;
char sexe ;
} Personne ; /* personne est le nom du type */
Personne pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 9


Remarques
1. Pour le cours « algorithme et programmation III » on vous
suggère d'utiliser la 4ème méthode pour déclarer une structure.
2. Avec la 4ème méthode pour déclarer une structure :
 Personne est le nom du type structure disposant de 4 champs :
 numéro est le nom d'un champ de type entier.
 taille et poids sont deux champs de type réels.
 sexe est un champ de type caractère.
 pers1 et pers2 sont deux variables de type structure dont
le nom est Personne.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 10


Accès à un champ d'une structure
 Le langage C utilise le point "." pour accéder à un champ d'une variable
de type structure : variable_de_type_structure.champ
 Écrire les instructions pour donner à la variable "pers1" les affectations
suivantes : C'est un homme qui mesure 1.67 mètre et pèse 67.8 kg. Son
numéro d'identification est 7234.

pers1.numero = 7234 ;
pers1.sexe = 'M' ;
pers1.taille = 1.67 ;
pers1.poids = 67.8 ;

 Écrire les instructions pour afficher les informations de "pers1" à l'écran :


printf("Son numéro : %d\n", pers1.numero);
printf("Son sexe : %c\n", pers1.sexe);
printf("Son poids : %.2f kgs\n", pers1.poids);
printf("Sa taille : %.2f m\n", pers1.taille);

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 11


Rappel: Variable vs Pointeur ?
Mémoire RAM :

1B0 1B1 1B2 1B3 1B4 1B5 1B6 1B7 1B8


mémoire

1B9 1C0 1C1 1C2 1C3 1C4 1C5 1C6 1C7


Case

1C8 1C9 1D0 1D1 1D2 1D3 1D4 1D5 1D6

1D7 1D8 1D9 1E0 1E1 1E2 1E3 1E4 1E5

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 12


Rappel: Variable vs Pointeur ?
Mémoire RAM :

7 int a;
a=7;
1B0 1B1 1B2 1B3 1B4 1B5 1B6 1B7 1B8
int * P;
1B2 P=&a;
mémoire

1B9 1C0 1C1 1C2 1C3 1C4 1C5 1C6 1C7


Case

1C8 1C9 1D0 1D1 1D2 1D3 1D4 1D5 1D6

1D7 1D8 1D9 1E0 1E1 1E2 1E3 1E4 1E5

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 13


Rappel: Pointeur ?
 C’est quoi une variable ?
Une variable est une zone mémoire RAM. C'est une sorte de boîte,
étiquetée, où l'on peut stocker de l'information pour la consulter ou la
modifier plus tard.

 C’est quoi un pointeur ?


Un pointeur est une variable qui peut contenir l’adresse d’une autre
variable.

Si un pointeur P contient l’adresse d’une variable A on dit que “P pointe sur


A”.
Les opérateurs de base :
& : pour obtenir l’adresse d’une variable
* : pour accéder au contenu d’une variable

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 14


Cas spécial : Pointeur vers le type structure
 Avec la déclaration : Personne * P ;
 P est un pointeur vers le type Personne.
 *P est une variable de type Personne.

 On peut accéder à n'importe quel champ de *P :


 (*P).taille, (*P).poids, …
 Le langage C permet de simplifier l'écriture en utilisant l'opérateur ->

(*P).champ P->champ
Équivalent à

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 15


Types de base et Écriture formatée de
données
Type Description Nombre d'octets Le format
Les types entiers
int entier standard 2 %d ou %i
char caractère 1 %c
Char * chaîne de caractères 1 %s
Les types Rationnels
float Réel simple 4 %f
double Réel double 8 %f ou %e
long double Réel double 10 %Lf

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 16


La fonction sizeof ( type ou nom de variable)
 sizeof fournit la taille (en octets) du type ou de la variable qui suit.
Sa syntaxe est : sizeof ( type ou nom de variable)
 int n ;
sizeof(n) peut valoir 2 ou 4 selon l'ordinateur et le logiciel .
#include <stdio.h>

int main() {

printf("un int est codé sur %d octets\n",sizeof(int));


printf("un float est codé sur %d octets\n",sizeof(float));
printf("un double est codé sur %d octets\n",sizeof(double));
printf("un char est codé sur %d octets\n",sizeof(char));

return 0;
}

 Question : Quel est le nombre d’octets réservés en mémoire après la


déclaration de la structure Personne ?

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 17


Allocation de la mémoire

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 18


Allocation de mémoire : Types de données
 L’allocation de mémoire en programmation est très importante pour
stocker des valeurs lorsque vous les affectez à des variables.
 L’attribution est faite avant et/ou au moment de l’exécution du
programme.
 Les données statiques occupent un emplacement parfaitement défini
lors de la compilation.
 Les données dynamiques n’ont pas non plus de taille définie a priori,
leur création ou leur libération dépend, cette fois, de demandes
explicites faites lors de l’exécution du programme.
 La mémoire peut être allouée de deux manières soit
automatique(statique) ou dynamique.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 19


Allocation automatique (statique)
 La mémoire allouée est fixe. Une fois la mémoire allouée, elle ne
peut plus être changée.
 Si le programmeur écrit float T[24]; T est un tableau pouvant
stocker une séquence de données du même type.
 Alors, Il peut stocker 24 éléments réels. Il ne peut pas stocker plus
de 24 éléments.
Exemple : un tableau qui stocke les notes des étudiants d’une classe :
#include<stdio.h>
int main(){
float T[24] ; int i ;
for(i=0 ;i<24 ;i++){
printf(“donner la note : “) ;
scanf(“%f“,&T[i]);
}
return 0;
};
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 20
Allocation automatique(statique) :
Désavantages
 Dans la plupart des cas, c'est un gaspillage de mémoire si on utilise une
petite partie de l'espace réservé.
 Avec l’allocation automatique, ajouter ou diminuer la taille de la
mémoire réservée est impossible.

 Pour résoudre ce problème le langage C propose l’allocation


dynamique de la mémoire :

Allocation
mémoire

Allocation Allocation
stack heap dynamique
automatique

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 21


Allocation dynamique
 Dans un programme écrit en langage C, s’il est nécessaire de
changer la taille de la mémoire allouée, on utilise l’allocation
dynamique.
 L’allocation dynamique consiste à réserver un espace mémoire pour
stocker l’objet pointé.
 En fonction d’ajout et de suppression, la mémoire peut être
augmenté ou diminuée.
 On utilise souvent la fonction "malloc" (memory allocation) qui est
déclarée dans le fichier d'en-tête <stdlib.h>.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 22


La fonction malloc
void * malloc(nombre_octets) ; (stdlib.h)

Pointeur NULL
qui pointe vers l’espace réservé échec de réservation

 Demande au système d’exploitation la permission d’utiliser


de la mémoire.
 Cette allocation est effectuée en trois étapes :
1) Appeler malloc pour demander de la mémoire
2) Vérifier la valeur retournée par malloc pour savoir si le S.E a bien
réussi à allouer la mémoire.
3) Une fois qu’on a fini d’utiliser la mémoire, on doit la libérer avec free

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 23


La fonction malloc
Exemple 1 : int * T ;
T = (int *) malloc (sizeof(int));
 On demande d'allouer 4 octets (sizeof(int) vaut 4)
pour mémoriser *p qui est de type entier.
 Pour allouer un espace mémoire pour un tableau de n cases de type
int, il suffit d’écrire malloc(n* (sizeof(int)), n doit être saisi avant de
faire appelle à malloc.
Exemple 2 :
char * nomPre ;
nomPre = (char *) malloc (30) ;
 On demande d'allouer 30 octets pour mémoriser un nom et un prénom .

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 24


La fonction malloc
Exemple 3 :
typedef struct
{

......

} Etudiant ;
Etudiant * p ;
p = (Etudiant *) malloc ( sizeof(Etudiant)) ;

 On demande d'allouer le nombre d'octets nécessaires pour


mémoriser *p qui est de type Etudiant.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 25


La fonction malloc : Cas général
 Soit T le nom d'un type prédéfini (int, char, etc ...) ou inventé par
le programmeur (comme Etudiant, Employe, Personne, etc ...).
 Allocation dynamique se fait par l'affectation suivante :

p = (T *) malloc (sizeof(T));
 sizeof(T) donne la taille de T en nombre d'octets (de Bytes).
 On demande l'espace mémoire pour stocker *p et on dépose
l'adresse de *p dans p.
 Cette affectation est représentée par le schéma suivant:

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 26


La fonction calloc
void * calloc(number_element, taille_element); (stdlib.h)

 Cette fonction a quasiment le même comportement que la


fonction malloc.
 calloc se charge aussi d'initialiser la zone mémoire allouée en y mettant
tout les octets à la valeur 0 (ce qui n'est pas le cas de malloc).
 Number_element: permet de déterminer le nombre de blocs
consécutifs à allouer.
 Taille_element : permet de fixer la taille (en nombre
d'octets). Au final, la zone de mémoire allouée occupera
donc number * taille octets.
Exemple :
#define INT_NUMBER 10
int * pointer = (int *) calloc( INT_NUMBER, sizeof(int) );

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 27


La fonction realloc
void * realloc (pointeur, taille_octet ) (stdlib.h)

 realloc permet de modifier la taille d’une zone préalablement


allouée (par malloc, calloc ou realloc).
 Le pointeur doit être l’adresse de début de la zone dont on veut
modifier la taille.
 Quant à taille_octet représente la nouvelle taille souhaitée.
 Cette fonction restitue l’adresse de la nouvelle zone ou un pointeur
NULL dans le cas où l’allocation a échoué.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 28


La fonction free
void free (pointeur) (stdlib.h)

 La fonction free() est utilisée pour libérer la mémoire allouée.

 Si nous n'avons plus besoin d'un bloc de mémoire que nous avons
réservé, alors nous pouvons le libérer à l'aide de la fonction free de
la bibliothèque <stdlib.h>.
 libère le bloc de mémoire désigné par le <Pointeur>; n'a pas d'effet si
le pointeur a la valeur NULL.
 Si nous ne libérons pas explicitement la mémoire à l'aide free, alors
elle est libérée automatiquement à la fin du programme.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 29


Application
 Nous cherchons à manipuler les données des salariés (personnes)
d’une entreprise sous forme de structure avec les champs suivants :
 numero : entier
 nom : chaîne de caractères.
 salaire : réels.

1) Donner la déclaration de la structure personne.


2) Ecrire une fonction qui permet de saisir les informations des employés.
3) Ecrire la fonction qui permet calculer la somme des salaires de tous les
employés.
4) Ecrire une fonction qui permet de calculer une augmentation de 10% des
salaires pour tous les employés.
5) Ecrire une fonction qui permet d’afficher les noms et les salaires des
employé.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 30


Solution
#include<stdio.h>
#define NMAX 10
typedef struct{ int numero;
char nom[20];
float salaire;
}personne;

void lecture (personne p[], int n )


{ int i;
for(i=0;i<n;i++){
printf("donner numéro\n"); scanf("%d",&p[i].numero);
printf("donner nom\n"); scanf("%s",p[i].nom);
printf("donner salaire\n"); scanf("%f",&p[i].salaire);
}}

float somme (personne p[], int n)


{ int i;float somme=0;
for(i=0;i<n;i++){
somme+=p[i].salaire;
}
return somme;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 31


Solution
personne * augmentation (personne p[], int n)
{ int i; personne *P1 ;
P1=(personne *)malloc(n*sizeof(personne));
for(i=0;i<n;i++){
P1[i].numero=P[i].numero;
strcpy(P1[i].nom,p[i].nom);
P1[i].salaire=p[i].salaire+0.1*p[i].salaire;}
return P1;
}
void afficher (personne p[], int n)
{ int i;
for(i=0;i<n;i++){
printf("nom=%s\n",p[i].nom);
printf("salaire=%f\n",p[i].salaire);
}
}
int main ()
{ personne p1[10],*p2; float s=0;
lecture (p1,3);
s=somme(p1,3);
afficher(p1,3);
p2=augmentation(p1,3);
afficher(p2,3);
system("pause");
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 32
Remarques
 Pour modifier le contenu d’un paramètre d’une fonction, utiliser un
passage par adresse.
 Si on utilise un tableau statique dans le paramètre d’une fonction
cela signifie qu’on utilise un passage par adresse car le nom du
tableau c’est un pointeur.

Exemple :

float somme (personne p[], int n)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 33


Remarques
 Si vous voulez récupérer plusieurs valeurs en résultat de traitement
d’une fonction, utiliser comme déclaration de votre fonction la
syntaxe suivants :
 type_de_retour * nom_de_fonctions (paramètres )

Exemple :

personne * augmentation (personne p[], int n)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 34


Chapitre 1:
Listes simplement chaînées

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 35


plan
 Définition
 Représentation
 Opérations
 Initialisation
 Ajout
 Suppression
 Affichage
 Destruction

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 36


Une liste chaînée … c’est quoi?
 Une liste linéaire chaînée est une structure de données qui utilise la
notion des pointeurs et l'allocation dynamique.
 Une liste chaînée est une collection d’élément de même type.
 Chaque élément est lié à son successeur et il n'est donc pas possible
d'accéder directement à un élément quelconque de la liste.
 Il suffit de connaître l’adresse du premier élément de la liste ( Tête de la
liste) pour accéder à tous ses éléments.
 Exemple :
L
tête de la liste

10 55 8 12 13 70

@058 @2589 @321 @898 @901 @352


Un ensemble d’éléments dispersés dans
la mémoire contenant des entiers
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 37
Comparaison avec un tableau
 Un tableau est une collection de données de même types.
 Il suffit de connaître l’adresse du tableau T(première case) pour accéder à
tous ses éléments.

T 0 1 2 3 4 5
10 55 8 12 13 70
@100 @104 @108 @112 @116 @120

Un ensemble d’éléments contigus dans la mémoire


contenant des entiers

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 38


Liste chaînée vs Tableau
Déclaration d’une liste chaînée L :
L
10 55 8 12 13 70

@058 @2589 @321 @898 @901 @352


L est la première adresse ou la tête de la liste.
Pour un tableau T : int T[6]

T 0 1 2 3 4 5

10 55 8 12 13 70
@100 @104 @108 @112 @116 @120

T est la première adresse ou le nom du tableau

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 39


Liste chaînée vs Tableau
 Déclaration d’une liste chaînée L :

13
Elément d’une liste chaînée
?
@901

indice
4
Elément d’un tableau 13 4 est l’indice de la cinquième case

@116

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 40


Liste chaînée vs Tableau
 Déclaration d’une liste chaînée L :
Information de
l’élément
Elément
@suivant

L
10 55 8 12 13 70
@2589 @ 321 @ 898 @ 901 @ 352 @NULL
@ 058 @2589 @ 321 @ 898 @ 901 @ 352

0 1 2 3 4 5

 Déclaration d’un tableau T : 10 55 8 12 13 70


@100 @104 @108 @112 @116 @120

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 41


Déclaration d’une liste chainée
 Une liste est représentée par un pointeur qui pointe vers son
premier élément(type structuré). Chaque élément est une
structure ayant deux champs :
1.Un champ pour le contenu
2.Un autre champ particulier qu’est l’adresse de l’élément
suivant
typedef struct element{

type contenu;
struct element * suivant;

}ElementListe;
ElementListe * L;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 42


Déclaration d’une liste chainée
 Remarques
1. Pour avoir le contrôle de la liste il est nécessaire de sauvegarder
l’adresse du premier élément.
2. L est un pointeur qui pointe vers un objet de type ElementListe.
3. *L est de type ElementListe.
4. (*L).contenu peut s'écrire L->contenu
5. (*L).suivant peut s'écrire L->suivant

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 43


Déclaration d’une liste chainée
 Remarques
6. Avec la déclaration : ElementListe * tempo ;
L'affectation : tempo = (ElementListe *) malloc (sizeof(ElementListe));
est représentée par le schéma suivant :

On ne connaît pas le champ "valeur" ni le champ "suivant"


de *tempo.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 44


Déclaration d’une liste chainée
 Exemple
Écrire les déclarations d'une liste linéaire chaînée des employés.
 Solution :
#define MAX_EMP 2000
#define LONG_NOM 30
typedef struct {
int numero ;
char nom[LONG_NOM] ;
float taille, salHebdo ;
} Employe ;

typedef struct Elem {


Employe emp ;
struct Elem * suivant ;
} Element;

Element *L ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 45


Déclaration d’une liste chainée
 Nous allons travaillé dans ce qui suit par les déclarations
suivantes :

typedef struct element{

int contenu;
struct element * suivant;

}ElementListe;
ElementListe * L;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 46


Opérations sur les listes chaînées :
 Initialisation
Prototype de la fonction : ElementListe * initialisation (ElementListe * L);

 Cette opération doit être faite avant toute autre opération sur la liste.

 Elle initialise le pointeur L avec la valeur NULL.


La fonction
Ou bien
ElementListe * initialisation (ElementListe *L) { int main() {
ElementListe *L;
L= NULL;
L= NULL;
return L; ..
} ..
..
return 0;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 47


Opérations sur les listes chaînées :
 Allocation de la mémoire pour le nouvel élément (1/2)

 Cette opération permet d’allouer de l’espace mémoire pour un élément de la liste


avant de l’insérer.

 Initialiser le pointeur suivant par NULL.

 Le champs contenu sera rempli par la fonction insérer.


?
ElementListe * NE;

NE =(ElementListe *)malloc(sizeof(ElementListe )); NULL


NE ->suivant=NULL;

 Ou bien on peut nommer une fonction pour réaliser cette tâche :

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 48


Opérations sur les listes chaînées :
 Allocation de la mémoire pour le nouvel élément (2/2)
Prototype de la fonction : ElementListe * AllouerNoeud();

 Cette opération permet d’allouer de l’espace mémoire pour un élément de la liste


avant de l’insérer.

 Initialiser le pointeur suivant par NULL.


La fonction
ElementListe * AllouerNoeud() {
ElementListe * NE;
NE =(ElementListe *)malloc(sizeof(ElementListe ));
if (NE ==NULL) {printf("Memoire insuffisante\n"); exit(-1);}
else {NE ->suivant=NULL;
return NE;}
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 49
Opérations sur les listes chaînées :
 Insertion d'un élément dans la liste

 Pour ajouter un élément dans la liste il y a plusieurs situations :

 Insertion dans une liste vide.

 Insertion au début de la liste.

 Insertion à la fin de la liste.

 Insertion ailleurs dans la liste.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 50


Opérations sur les listes chaînées :
 Insertion d'un élément dans la liste
Algorithme :

Déclaration de l’élément à insérer(le nouvel élément).

Allocation de la mémoire pour le nouvel élément.

 Remplir le champ de données du nouvel élément.

 Mise à jour des pointeurs.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 51


Opérations sur les listes chaînées :
 Insertion dans une liste vide
Prototype de la fonction :

ElementListe * ins_dans_liste_vide (ElementListe * L, int donnee);


 Cette fonction permet de retourner l’adresse du premier nœud de la liste.

Insérer un nœud dans une liste vide.

La fonction

ElementListe * ins_dans_liste_vide (ElementListe * L, int donnee){


ElementListe * NE;

NE =AllouerNoeud();
NE->contenu=donnee;
L=NE;
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 52
Opérations sur les listes chaînées :
 Insertion au début de la liste
Prototype de la fonction :

ElementListe * ins_debut_liste (ElementListe * L, int donnee);


 Le pointeur suivant du nouvel élément pointe vers le premier élément.

 Le pointeur debut(L) pointe vers le nouvel élément.

donnee donnee donnee donnee


L
(2) suivant suivant suivant suivant

(1)
donnee NULL
suivant
Nouveau_Element /* NE */

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 53


Opérations sur les listes chaînées :
 Insertion au début de la liste
La fonction
ElementListe * ins_debut_liste (ElementListe * L, int donnee){
ElementListe * NE;
NE =AllouerNoeud();
NE->contenu=donnee;

if (L ==NULL) L=NE; // si la liste est vide


else {
NE ->suivant=L;
L=NE;}
return L;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 54


Opérations sur les listes chaînées :
 Insertion à la fin de la liste
Prototype de la fonction :

ElementListe * ins_fin_liste (ElementListe * L, int donnee);


 le pointeur suivant du dernier élément pointe vers le nouvel élément.
 le pointeur debut(L) ne change pas. Nouveau_Element

(*) (1) donnee

donnee donnee donnee donnee suivant


L
suivant suivant suivant suivant

NULL

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 55


Opérations sur les listes chaînées :
 Insertion à la fin de la liste
La fonction
ElementListe * ins_fin_liste (ElementListe * L, int donnee){
ElementListe * NE , * courant;
NE =AllouerNoeud();
NE->contenu=donnee;
if (L ==NULL) {L=NE;} // si la liste est vide
else {
// atteindre le dernier élément.
for(courant=L; courant->suivant!=NULL; courant=courant->suivant);
courant->suivant=NE;
}
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 56
Opérations sur les listes chaînées :
 Insertion ailleurs dans la liste
Prototype de la fonction :
ElementListe * ins_liste (ElementListe * L, int donnee, int pos);

 L'insertion s'effectuera après une certaine position passée comme argument


à la fonction. Si la position indiquée est le dernier élément, l'insertion sera
effectuée à la fin de la liste.

 Choisir une position dans la liste (l'insertion se fera après la position choisie)

 Le pointeur suivant du nouvel élément pointe vers l'adresse sur laquelle pointe
le pointeur suivant d'élément courant.

 Le pointeur suivant du l'élément courant pointe vers le nouvel élément

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 57


Opérations sur les listes chaînées :
 Insertion ailleurs dans la liste

(*)
donnee donnee donnee donnee
L
suivant suivant suivant suivant
(2)
(1) NULL
donnee
suivant
Nouveau_Element

 Question : Ecrire une fonction qui permet de calculer la taille d’une liste
(retourner le nombre d’éléments de la liste).

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 58


Opérations sur les listes chaînées :
 Insertion ailleurs dans la liste
La fonction
ElementListe * ins_liste (ElementListe * L, int donnee,int pos){ int i,taille=0;
ElementListe * NE , * courant;
NE =AllouerNoeud();
NE->contenu=donnee;
for(courant=L;courant; courant=courant->suivant) {taille++;}
if (pos >= 1 && pos <taille){
courant=L;
for(i=1;i<pos;i++) courant=courant->suivant;
NE->suivant = courant->suivant;
courant->suivant = NE;
}
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 59
Opérations sur les listes chaînées :
 Suppression d’un élément de la liste
 Pour supprimer un élément dans la liste il y a plusieurs situations :
 Suppression au début de la liste.
 Suppression ailleurs dans la liste.

Algorithme de suppression d'un élément de la liste


 Utilisation d'un pointeur temporaire pour sauvegarder l'adresse de
l’élément à supprimer.
 L'élément à supprimer se trouve après l'élément courant.
 Faire pointer le pointeur suivant de l'élément courant vers l'adresse
du pointeur suivant de l'élément à supprimer.
 Libérer la mémoire occupée par l'élément supprimé.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 60


Opérations sur les listes chaînées :
 Suppression au début de la liste
Prototype de la fonction:
ElementListe * supp_debut (ElementListe * L);
La fonction renvoie l’adresse du premier élément de la liste.
Algorithme :
 le pointeur elem_supp contiendra l'adresse du 1er élément
 le pointeur L pointera vers le 2ème élément
 libérer la mémoire occupée par l'élément supprimé

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 61


Opérations sur les listes chaînées :
 Suppression au début de la liste
(2)

(*)
donnee donnee donnee donnee
L
suivant suivant suivant suivant

(1) NULL

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 62


Opérations sur les listes chaînées :
 Suppression au début de la liste
la fonction:
ElementListe * supp_debut (ElementListe * L) {
ElementListe *elem_supp;
if (L==NULL) return L; /* liste vide */
elem_supp = L;
L = L->suivant;
free (elem_supp);
return L;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 63


Opérations sur les listes chaînées :
 Suppression ailleurs dans la liste
Prototype de la fonction:
ElementListe * supp_dans_liste (ElementListe *L, int pos);
La fonction renvoie l’adresse du premier élément de la liste.
Algorithme :
 Le pointeur elem_supp contiendra l'adresse vers laquelle pointe le
pointeur suivant d'élément courant.
 Le pointeur suivant de l'élément courant pointera vers l'élément sur
lequel pointe le pointeur suivant de l'élément qui suit l'élément
courant dans la liste.
 Libérer la mémoire occupée par l'élément supprimé

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 64


Opérations sur les listes chaînées :
 Suppression ailleurs dans la liste
(2)

(*)
donnee donnee donnee donnee donnee
L
suivant suivant suivant suivant suivant

(1) NULL

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 65


Opérations sur les listes chaînées :
 Suppression ailleurs dans la liste
la fonction: /* supprimer un élément après la position demandée */
ElementListe * supp_dans_liste (ElementListe *L, int pos){ int i,taille=0;
ElementListe *elem_supp, *courant;
for(courant=L;courant; courant=courant->suivant) {taille++;}
if (pos >= 1 && pos <taille){ courant=L;
for (i = 1; i<pos; i++) courant = courant->suivant;
elem_supp = courant->suivant;
courant->suivant = elem_supp->suivant;
free (elem_supp); }
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 66
Opérations sur les listes chaînées :
 Affichage de la liste
 Pour afficher la liste entière il faut se positionner au début de la liste (le pointeur L le
permettra).
 La condition d'arrêt est donnée par le pointeur suivant du dernier élément qui vaut NULL.
 La fonction
void affichage (ElementListe * L)
{
ElementListe *courant;
courant = L;
while (courant != NULL)
{ printf (" %d\n", courant->contenu);
courant = courant->suivant;
}
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 67
Opérations sur les listes chaînées :
 Destruction de la liste
 Pour détruire la liste entière, on supprime le début de la
liste tant que L est différent de NULL.
 La fonction
/* détruire la liste */
ElementListe * detruire (ElementListe * L) {
while (L!=NULL) L=supp_debut (L);
return L;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 68


Liste chaînée circulaire

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 69


Liste chaînée circulaire :
 Représentation
Sur une liste chainée, si le pointeur du dernier nœud
pointe sur le premier nœud on dit que la liste est
circulaire.

donnee donnee donnee donnee


L
suivant suivant suivant suivant

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 70


Liste chaînée circulaire :
 Insertion au début de la liste
Algorithme :
 Créer un Nouveau_Element et faire pointer le suivant de
Nouveau_Element sur le début de la liste.
 Aller au dernier nœud, puis pointer son suivant sur
Nouveau_Element
 Faire de Nouveau_Element, le nouveau pointeur de début.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 71


Liste chaînée circulaire :
 Insertion au début de la liste
donnee donnee donnee donnee
L
suivant suivant suivant suivant
(3) Nouveau_Element

donnee
(1)
suivant
(2)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 72


Chapitre 2 :
Listes doublement chaînées

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 73


plan
 Définition
 Représentation
 Opérations
 Initialisation
 Ajout
 Suppression
 Affichage
 Destruction

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 74


LSC vs LDC
 Déclaration d’une liste Simplement chaînée L :
Information de
l’élément
Elément
@suivant

L 10 55 8 12 13 70
@2589 @ 321 @ 898 @ 901 @ 352 @NULL
@ 058 @2589 @ 321 @ 898 @ 901 @ 352

 Déclaration d’une liste Doublement chaînée L :


@précèdent
Elément Information de l’élément
@suivant
@NULL @ 058 @2589 @ 321 @ 898 @ 901
L 10 55 8 12 13 70
@2589 @ 321 @ 898 @ 901 @ 352 @NULL
@ 058 @2589 @ 321 @ 898 @ 901 @ 352

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 75


Liste doublement chaînée … c’est quoi?
 Les Listes Doublement Chaînées sont des structures de données
semblables aux listes simplement chaînées, sauf que le chaînage se
fait dans les deux sens, ce qui permet de parcourir la liste en avant
comme en arrière, par ailleurs:
 L'allocation de la mémoire est faite au moment de l'exécution.
 La liaison entre les éléments se fait grâce à deux pointeurs (un qui
pointe vers l'élément précédent et un qui pointe vers l'élément suivant)
 Le pointeur précèdent du premier élément doit pointer vers NULL (c’est
le début de la liste).
 Le pointeur suivant du dernier élément doit pointer vers NULL (c’est la
fin de la liste)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 76


Liste doublement chaînée
 Pour accéder à un élément de la liste doublement chaînée :
 En commençant avec la tête : le pointeur suivant permet le déplacement
vers le prochain élément
 En commençant avec la queue : le pointeur precedent permet le
déplacement vers l'élément précédent

precedent precedent precedent precedent


NULL donnee donnee donnee donnee NULL
L suivant suivant suivant suivant

 La liste doublement chaînée peut être parcourue dans les deux sens, du
premier vers le dernier élément et/ou du dernier vers le premier élément.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 77


Déclaration d’une liste doublement chaînée
 L'élément de la liste contiendra un champ donnee, un pointeur
precedent et un pointeur suivant.
 Les pointeurs precedent et suivant doivent être du même type que
l'élément, sinon ils ne pourront pas pointer vers un élément de la liste.
 Le pointeur precedent permettra l'accès vers l'élément précédent
tandis que le pointeur suivant permettra l'accès vers le prochain
élément.

typedef struct element{

type contenu;
struct element * suivant;
struct element * precedent;

}ElementListe;
ElementListe * L;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 78


Déclaration d’une liste doublement chaînée
 Exemple 1 : Représentation d’une liste de 5 éléments ‘A’, ‘B’,‘C’,‘D’
et ‘E’ :
typedef struct element {

char donnee;
struct element * suivant;
struct element * precedent;

}ElementListe;
ElementListe * L;

 Pour avoir le contrôle de la liste il est préférable de sauvegarder


l'adresse du premier élément de la liste. ElementListe * L ;

A B C D E

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 79


Déclaration d’une liste doublement chaînée
 Nous allons travaillé dans ce qui suit par les déclarations suivantes :

typedef struct element {

char info[10];
struct element * suivant;
struct element * precedent;

}ElementListe;
ElementListe * L;

Ali Mohamed Amine Sarah

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 80


Opérations sur les LDC :
 Initialisation
Prototype de la fonction : ElementListe * initialisation (ElementListe * L);

 Cette opération doit être faite avant toute autre opération sur la liste.

 Elle initialise le pointeur L avec la valeur NULL.


La fonction
Ou bien
ElementListe * initialisation (ElementListe *L) { int main() {
ElementListe *L;
L= NULL;
L= NULL;
return L; ..
} ..
..
return 0;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 81


Opérations sur les LDC :
 Allocation de la mémoire pour le nouvel élément
Prototype de la fonction : ElementListe * AllouerNoeud();

 Cette opération permet d’allouer de l’espace mémoire pour


un élément de la liste avant de l’insérer.

 Initialiser le pointeur suivant par NULL

 Initialiser le pointeur precedent par NULL

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 82


Opérations sur les LDC :
 Allocation de la mémoire pour le nouvel élément
La fonction NULL
?
ElementListe * AllouerNoeud() {
NULL
ElementListe * NE;
NE =(ElementListe *)malloc(sizeof(ElementListe ));
if (NE ==NULL) {printf("Memoire insuffisante\n"); exit(-1);}
else {
NE ->suivant=NULL;
NE ->precedent=NULL,
return NE;}
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 83


Opérations sur les LDC :
 Insertion d'un élément dans la liste

 Pour ajouter un élément dans la liste il y a plusieurs situations :

 Insertion dans une liste vide

 Insertion au début de la liste

 Insertion à la fin de la liste

 Insertion ailleurs dans la liste

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 84


Opérations sur les LDC :
 Insertion d'un élément dans la liste
Algorithme :

 Déclaration de l’élément à insérer(le nouvel élément)

 Allocation de la mémoire pour le nouvel élément

 Remplir le champ de données du nouvel élément

 Mise à jour des pointeurs (précédent et suivant)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 85


Opérations sur les LDC :
 Insertion dans une liste vide
Prototype de la fonction :
ElementListe * ins_dans_liste_vide (ElementListe * L, char * info);
 Cette fonction permet de retourner l’adresse du premier nœud de la liste.

Insérer un nœud dans une liste vide.

La fonction
ElementListe * ins_dans_liste_vide (ElementListe * L, char *info){
ElementListe * NE;
NE =AllouerNoeud();
◦ strcpy(NE->info,info);
L=NE;
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 86
Opérations sur les LDC :
 Insertion au début de la liste
Prototype de la fonction :
ElementListe * ins_debut_liste (ElementListe * L, char * info);

 Le pointeur suivant du nouvel élément pointe vers le 1er élément.

 Le pointeur précèdent du 1er élément pointe vers le nouvel élément.

 Le pointeur debut(L) pointe vers le nouvel élément.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 87


Opérations sur les LDC :
 Insertion au début de la liste

NULL precedent precedent precedent


L donnee donnee donnee NULL
(3) (2) suivant suivant suivant

precedent (1)
donnee
suivant
Nouveau_Element

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 88


Opérations sur les LDC :
 Insertion au début de la liste
La fonction
ElementListe * ins_debut_liste (ElementListe * L, char * info){
ElementListe * NE;
NE =AllouerNoeud();
◦ strcpy(NE->info,info);
if (L ==NULL) {L=NE;} // si la liste est vide
else { NE -> suivant=L;
L-> precedent=NE;
L=NE;}
return L;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 89


Opérations sur les LDC :
 Insertion à la fin de la liste
Prototype de la fonction :
ElementListe * ins_fin_liste (ElementListe * L, char * info);

 le pointeur suivant du dernier élément pointe vers le nouvel élément.

 le pointeur précédent du nouvel élément pointe vers le denier élément.

 le pointeur debut(L) ne change pas.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 90


Opérations sur les LDC :
 Insertion à la fin de la liste
(*)
NULL precedent precedent precedent NULL
(2)
donnee donnee donnee
L
suivant suivant suivant
precedent
(1)
donnee
suivant
Nouveau_Element

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 91


Opérations sur les LDC :
 Insertion à la fin de la liste
La fonction
ElementListe * ins_fin_liste (ElementListe * L, char * info){
ElementListe * NE , * courant;
NE =AllouerNoeud();
◦ strcpy(NE->info,info);
if (L ==NULL) {L=NE;} // si la liste est vide
else {
// atteindre le dernier élément
for(courant=L; courant->suivant!=NULL;courant=courant->suivant);

courant->suivant=NE;
NE->precedent=courant;}
return L;}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 92
Opérations sur les LDC :
 Insertion ailleurs dans la liste
Prototype de la fonction :
ElementListe * ins_liste (ElementListe * L, char * info, int pos);

 L'insertion s'effectuera après(ou avant) une certaine position passée comme


argument à la fonction.

 Si la position indiquée est le dernier élément, l'insertion sera effectuée à la


fin de la liste.

 La position indiquée ne doit pas être le 1er élément. Dans ce cas il faut
utiliser la fonction d'insertion au début de la liste.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 93


Opérations sur les LDC :
 Insertion ailleurs dans la liste
Les étape : Insertion après un élément de la liste
 choisir une position dans la liste

 le pointeur suivant du nouvel élément pointe vers l'adresse sur la quelle


pointe le pointeur suivant d'élément courant

 le pointeur precedent du nouvel élément pointe vers l'élément courant.

 le pointeur precedent de l'élément qui succède l'élément courant


pointera vers le nouvel élément

 le pointeur suivant d'élément courant pointe vers le nouvel élément

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 94


Opérations sur les LDC :
 Insertion ailleurs dans la liste
(*)
NULL precedent precedent precedent

L donnee donnee donnee NULL


(2) (3)
suivant suivant suivant
precedent
(4) (1)
donnee
suivant
Nouveau_Element

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 95


Opérations sur les LDC :
 Insertion ailleurs dans la liste
La fonction
ElementListe * ins_liste (ElementListe * L, char * info, int pos){ int i,taille=0;
ElementListe * NE , * courant;
NE =AllouerNoeud();
strcpy(NE->info,info);
for(courant=L;courant; courant=courant->suivant) {taille++;}
if (pos >= 1 && pos <taille){
courant=L;
for(i=1;i<pos;i++) courant=courant->suivant;

NE->suivant = courant->suivant;
NE->precedent = courant;
courant->suivant->precedent = NE;
courant->suivant = NE;}
return L;}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 96


Opérations sur les LDC :
 Suppression d’un élément de la liste
 La suppression au début et à la fin de la L.D.C ainsi qu'avant ou après un
élément revient à la suppression à la position 1 ou à la position N (nombre
d'éléments de la liste) ou ailleurs dans la liste.

 La suppression dans la L.D.C à n'importe quelle position ne pose pas des


problèmes grâce au pointeurs precedent et suivant, qui permettent de
garder la liaison entre les éléments de la liste.

 C'est la raison pour la quelle nous allons créer une seule fonction.

 Si nous voulons supprimer :


• l'élément au début de la liste nous choisirons la position 1
• l'élément à la fin de la liste nous choisirons la position N
• un élément quelconque alors on choisit sa position dans la liste

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 97


Opérations sur les LDC :
 Suppression au début de la liste
Les étapes :
La position choisie est 1 (suppression du 1er élément de la liste) :
 Le pointeur elem_supp contiendra l'adresse du 1er élément.
 Le pointeur L contiendra l'adresse contenue par le pointeur suivant du
1er élément que nous voulons supprimer.
 Nous faisons pointer le pointeur precedent du 2ème élément vers
NULL).

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 98


Opérations sur les LDC :
 Suppression au début de la liste
(2)

(*)
precedent precedent precedent precedent
L
donnee donnee donnee donnee NULL
NULL suivant suivant suivant suivant

(3)
(1)

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 99


Opérations sur les LDC :
 Suppression à la fin de la liste
Les étapes :
La position choisie est égale au nombre d'éléments de la liste :
 Le pointeur elem_supp contiendra l'adresse du dernier élément
 Nous faisons pointer le pointeur suivant de l'avant dernier élément
vers NULL.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


100
Opérations sur les LDC :
 Suppression à la fin de la liste

(*)
precedent precedent precedent precedent
L
donnee donnee donnee donnee
NULL
NULL suivant suivant suivant suivant

(1)
(2)

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


101
Opérations sur les LDC :
 Suppression d’un élément dans la liste
Les étapes :
La position choisie est aléatoire dans la liste :
 Le pointeur elem_supp contiendra l'adresse de l'élément à supprimer
 Le pointeur suivant d'élément qui précède l'élément à supprimer
pointe vers l'adresse contenu par le pointeur suivant d'élément à
supprimer
 Le pointeur precedent d'élément qui succède l'élément à supprimer
pointe vers l'adresse contenu par le pointeur precedent d'élément à
supprimer.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


102
Opérations sur les LDC :
 Suppression ailleurs dans la liste
(2)
(*)
precedent precedent precedent precedent
L
donnee donnee donnee donnee NULL
NULL suivant suivant suivant suivant

(3)
(1)

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


103
Opérations sur les LDC :
 Suppression d’un élément dans la liste
la fonction:
ElementListe * supp_dans_liste (ElementListe *L, int pos){ int i,taille=0;
ElementListe *elem_supp, *courant;
for(courant=L;courant; courant=courant->suivant) {taille++;}
if(taille == 0) return L;
if(pos == 1) { /* suppression du 1er élément */
elem_supp = L;
L = L->suivant;
if(L == NULL) free(elem_supp); return L;
else L->precedent = NULL;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
104
Opérations sur les LDC :
 Suppression d’un élément dans la liste

else if(pos == taille) { /* suppression du dernier élément */


for(courant = L; courant->suivant!=NULL; courant = courant->suivant);
elem_supp = courant;
courant->precedent->suivant = NULL;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


105
Opérations sur les LDC :
 Suppression d’un élément dans la liste

else { /* suppression ailleurs */


courant = L;
for(i=1;i<pos;i++) courant = courant->suivant;
elem_supp = courant;
courant->precedent->suivant = courant->suivant;
courant->suivant->precedent = courant->precedent;
}
free(elem_supp);
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
106
Opérations sur les LDC :
 Affichage de la liste
 Pour afficher la liste entière

 se positionner au début de la liste(L) ou à la fin de la liste.

 parcourir la liste du 1er vers le dernier élément ou du


dernier vers le 1er élément en utilisant le pointeur suivant
ou précèdent de chaque élément.

 La condition d'arrêt est donnée par le pointeur suivant du


dernier élément qui vaut NULL ou le pointeur précèdent du
1er élément qui vaut NULL.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


107
Opérations sur les LDC :
 Affichage de la liste
void afficher_Liste(ElementListe * L) { /* affichage en avançant */
ElementListe *courant;
courant = L; /* point du départ le 1er élément */
printf("{");
while(courant != NULL) {
printf(" %s\t ", courant->info);
courant = courant->suivant;
}
printf("}\n");
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
108
Opérations sur les LDC :
 Destruction de la liste
 Pour détruire la liste entière, on doit supprimer élément par élément

 La suppression peut être commencer par la position 1 tant que la taille


est plus grande que 0.

 La fonction
/* détruire la liste */
ElementListe *detruire (ElementListe * L) {

while (L!=NULL) {L=supp_dans_liste (L, 1);}


return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
109
Chapitre 3 : Les piles

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 110


plan
 Définition d’une pile
Utilisations
 Représentation d’une pile
 Dynamique
 Statique
 Opérations
 Initialiser
 Empiler
 Dépiler
 Afficher
 Détruire

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 111


Définitions
 Une PILE (stack) est une structure de données dont une seule
extrémité est accessible -visible-
 Cette extrémité est appelée le sommet de la pile.
 L’extraction ou l’ajout se font au sommet de la pile.

Ajouter Extraire
Sommet

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 112


Principe LIFO
 Les PILEs suivent une démarche LIFO (Last In First Out) ce qui
signifie en clair que les derniers éléments à être ajoutés à la pile
seront les premiers à être récupérés.
 L’action d’ajouter un nouvel élément au sommet de la pile
s’appelle Empiler.
 L’action de retirer l’élément situé au sommet de la pile s’appelle
Dépiler.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 113


Utilisations
 La récursivité.
 La fonction « annuler la frappe » (Undo) d’un logiciel de
traitement de texte mémorise les modifications apportées au
texte dans une pile.
 Les piles peuvent être utilisées dans des algorithmes
d'évaluation des expressions mathématiques (vérification des
parenthèse d’une chaîne de caractère...)
 Dans un navigateur web, une pile sert à mémoriser les pages
web visitées.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 114


Utilisations
 Exemple : une pile d'assiette. Lorsqu'on ajoute une assiette en haut de la pile, on
retire toujours celle qui se trouve en haut de la pile : c'est à dire celle qui a été
ajoutée en dernier, sinon tout le reste s'écroule.

 Chaque problème qui utilise cette démarche peut être simulé (dans sa résolution)
par les piles.

D D

C C E E

B B B B B

A A A A A
dépilé dépilé empilé(E) empilé(D)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 115


Représentation

 Différentes représentations
Représentation dynamique
• listes simplement chaînées.
Représentation statique
• Un tableau et une variable globale indiquant le
sommet.
• Un enregistrement avec deux champs.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 116


- 1ème partie : Représentation dynamique -

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 117


Représentation chainée (par pointeurs)
 Les éléments de la pile sont chaînés entre eux.

 Chaque élément de la pile pointera vers l'élément suivant.

Le pointeur sommet devra toujours pointer vers le sommet


de la pile (le premier élément ).

 Une pile est vide si le pointeur sommet pointe sur NULL.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 118


Représentation chainée (par pointeurs)
 L’implémentation d’une pile est la même qu’une liste simplement chaînée avec la
règle suivante : « on ne peut agir que sur le sommet de la pile».

Ajout donnee Retrait


Sommet
suivant

donnee
suivant

donnee
suivant

donnee
NULL
suivant

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 119


Représentation
 La structure de la pile
 Nous allons créer une pile d'entiers (int)
 Notre pile sera basée sur une liste chaînée (simple)
 On suppose que la pile est déclarée de la façon suivante :

typedef struct Element {

int donnee; /*La donnée que notre pile stockera */


struct Element * suivant; /*Pointeur vers l'élément suivant */

} Pile;

Pile * sommet;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 120


Opération de base sur les Piles
 Initialisation
Prototype de la fonction : Pile * initialisation (Pile * sommet) ;
 Cette opération doit être faite avant toute autre opération sur la Pile.
 Elle initialise le pointeur sommet par NULL.

Fonction
Pile * initialisation (Pile * sommet) {
sommet = NULL;
return sommet;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 121


Opération de base sur les Piles
 Ajout d'un nouvel élément (empiler)
Prototype de la fonction : Pile * empiler(Pile * sommet, int donnee);

Algorithme de la fonction :

 Déclaration d'élément(s) à insérer

 Allocation de la mémoire pour le nouvel élément

 Remplir le contenu du champ de données

 Mettre à jour le pointeur sommet (le haut de la pile)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 122


Opération de base sur les Piles
 Ajout d'un nouvel élément (empiler) Ajout

(2) donnee

(1) suivant
Nouveau_Element
donnee
Sommet
suivant

donnee
suivant

donnee
suivant

donnee
NULL
suivant

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 123


Opération de base sur les Piles
 Ajout d'un nouvel élément
Fonction /* empiler (ajouter) un élément dans la pile */
Pile * empiler (Pile * sommet, int donnee) {
Pile * ne;
ne=AllouerNoeud();
ne->donnee=donnee;
if (sommet ==NULL) sommet=ne; // si la pile est vide
else {ne->suivant = sommet;
sommet = ne; }
return sommet;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 124


Opération de base sur les Piles
 Retrait d'un élément

 L'élément qui sera retiré de la pile sera le dernier élément


que l'on a ajouté (l’élément se trouvant au sommet de la pile).

Prototype de la fonction : Pile * depiler(Pile * sommet);

Algorithme de la fonction :
 le pointeur supp_elem contiendra l'adresse du pointeur sommet.

 le pointeur sommet pointera vers l’élément suivant du pointeur


sommet.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 125


Opération de base sur les Piles
 Retrait d'un élément

Retrait
donnee (1) Elem_supp
Sommet
suivant
(2)
donnee
suivant

donnee
suivant

donnee
NULL
suivant

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 126


Opération de base sur les Piles
 Retrait d'un élément

Fonction /*dépiler (supprimer) un élément de la pile*/.

Pile * depiler (Pile * sommet ) {


if (sommet==NULL) return sommet; /*pile vide*/
Pile *elem_supp;
elem_supp = sommet;
sommet = sommet->suivant;
free (elem_supp);
return sommet;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 127


Opération de base sur les Piles
 Affichage de la pile
 Il faut se positionner au sommet de la pile.
 En utilisant le pointeur suivant de chaque élément, la pile est parcourue du
haut vers le bas.
 La condition d'arrêt est : tant que courant != NULL.

void afficher ( Pile * sommet) {


Pile *courant;
courant = sommet;
while(courant != NULL) { printf(" %d\n", courant->donnee);
courant = courant->suivant;
}
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 128


Opération de base sur les Piles
 Destruction de la pile
 Il s'agit d’une fonction permettant d'effacer la Pile
Prototype de la fonction : Pile * pile_clear(Pile * sommet);
Algorithme de la fonction

Tant que le sommet n'est pas nul dépiler l’élément le plus haut de la pile.
Fonction :
Pile * pile_clear(Pile * sommet)

{
while (sommet != NULL) sommet=depiler(sommet);
return sommet;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 129


- 2ème partie : Représentation statique -

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 130


Les opérations de base sur la pile
 On suppose que la pile est déclarée de la façon suivante : Un enregistrement

avec deux champs

#define MAX 20
typedef struct{
char T[MAX];
int sommet;
} TPile;

TPile pile;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 131


Les opérations de base sur la pile
 fonction initialisation : initialiser la pile

void initialiser(TPile *pile) { pile->sommet= 0 ;}

 fonction Pile_vide : teste si la pile est vide ou non

int pile_vide(TPile pile) { return pile.sommet == 0;}

 fonction Pile_pleine : teste si la pile est pleine ou non

int pile_pleine(TPile pile) { return pile.sommet == MAX;}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 132


Les opérations de base sur la pile
 fonction Push : insérer(empiler) l’élément au sommet de la pile

void empiler(TPile * pile, char x)


{

if (pile_pleine(*pile)) { printf(" Stack overflow : dépassement de la capacité");}

else { pile->T[pile->sommet] = x;
pile->sommet++;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 133


Les opérations de base sur la pile
 fonction Pop : extraction (dépilement) de l’élément qui est au sommet
de la pile et le retourne comme valeur de la fonction.

char depiler(TPile * pile)

{ char x;

if (pilevide(*pile)) printf(" Stack Underflow : La pile est vide\n");

else {
pile-> sommet--;

x=pile->T[pile->sommet];

return x;}
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 134


Exemple d’application
 Traitement des expressions mathématiques
Exemple : (x + (y – (a + b)) * c – ( (d + e) ) )

 Si on a un seul type de délimiteur, on utilise un compteur :

+1 si on ouvre le délimiteur -1 si on ferme le délimiteur

 une expression est correcte si


 le compteur =0 à la fin

 ((x+y)+a-b) +1 +1 0 0 0 -1 0 0 0 0 -1 (compteur =0 expression correcte )

 )x+y)+a+(5-c( -1 0 0 0 -1 0 0 0 +1 0 0 0 +1 (compteur =0 mais expression incorrecte )

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 135


Exemple d’application
 traitement des expressions mathématiques
 La résolution de ce problème peut être donc simulée par la
structure de la pile.

 la dernière parenthèse ouverte est la première à être


fermée (LIFO).

 Donc, selon le type de la parenthèse :


 Parenthèse ouvrante: Empiler Parenthèse fermante: Dépiler

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 136


Exemple d’application
 Exemple : (x + (y – (a + b) ) * c – ( (d + e) ) )

( (

( (
(

( ( ( (

(x+(y-( (x+(y-(a+b)) …+b))*c-((d … ((d+e) … ((d+e)))


expression
correcte
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 137
Exemple d’application
#include <stdio.h>

#include <stdlib.h>

#define MAX 10

typedef struct {

char T[MAX];

int sommet;

} TPile;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 138


Exemple d’application
main() {

TPile pile;

char exp[10];

int i=0;

int valide=1;// variable utilisée comme un témoin

printf("saisir l expression a verifier :\n");

scanf("%s",exp);

initialiser(&pile);

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 139


Exemple d’application
while(exp[i] !='\0' && valide==1 )
{ if (exp[i]=='(') empiler(&pile,exp[i]);
if (exp[i]==')')
{ if(pilevide(pile)) valide=0;
else depiler(&pile); }
i++;
}// fin while
if (pilevide(pile)&&(valide==1)) printf("expression correcte\n");
else printf("expression non correcte\n");
return 0;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 140


Chapitre 4 : Les files

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


141
plan
 Définition d’une file
Utilisations
 Représentation d’une file
 Statique
 Dynamique
 Opérations
 Initialiser
 Enfiler
 Défiler
 Afficher
 Détruire

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


142
Définitions
 Une FILE (en anglais queue) est une structure de donnée dans laquelle
l’insertion se fait à la fin et la suppression d’un élément s’effectue à partir
du début de cette structure.

 Le fonctionnement ressemble à une file d’attente : les premières


personnes arrivées, se sont les premières personnes à servir.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


143
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s’ appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

[0] [1] [2] [3] [4]

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


144
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


145
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


146
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


147
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


148
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


149
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


150
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


151
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


152
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


153
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


154
Définitions
 Principe : une loi FIFO First In First Out le premier arrivé est le premier servi

 L’action d’ajouter un nouvel élément s ’appelle Enfiler.

 L’action de retirer un élément situé au début de la file s’appelle Défiler.

 Exemple : file d’attente

 dans le bus

 des requêtes destinées à un serveur

ar
Extraction av Insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


155
Utilisations
 Elle sont, en général utilisé pour mémoriser temporairement des transactions qui
doivent être attendre pour être traitées.

 Les serveurs d’impression, qui doivent traiter les requêtes dans l’ordre dans lequel
elles arrivent, et les insèrent dans une file d’attente (ou une queue);

 Certains moteurs multitâches, dans un système d’exploitation, qui doivent accorder du


temps-machine à chaque tâche, sans en privilégier aucune.

 Un algorithme de parcours en largeur utilise une file pour mémoriser les nœuds visités;

 On utilise aussi des files pour créer toutes sortes de mémoires tampons(en anglais
buffers)

 Etc.
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
156
Représentation

 Différentes représentations
 Représentation statique
Un vecteur qui représente la FILE F[Max] avec av et
ar deux variables globales indiquant la tête et
la queue de la file.
Un enregistrement avec trois champs.
 Représentation dynamique
 Listes simplement chaînées

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


157
- 1ère partie : Représentation statique -

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


158
Représentation
Représentation contiguë ( par tableau) :
 Les éléments de la file sont rangés dans un tableau qui représente la FILE
F[Max].
 av, ar deux variables globales de type entier indiquant la tête et la queue de
la file.
(1) (2) (3) ar (4) ar
ar C C
B B B av
A av A av

ar
av
inserer(C) extraire(A)
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
159
Les opérations de base sur la File
 initialisation : la file est vide au départ

ar  0 et av  0

 insertion de l’élément x : F[ar]  x et ar  ar+1

 extraction de l’élément x : x  F[av] et av  av+1

 Problème : du fait que les deux variables av et ar sont toujours


incrémentées, on arrive à un Overflow (file pleine) même si la file
n’est pas saturée (voir (4) on ne peut pas insérer un autre
élément)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


160
Les opérations de base sur la File
 une première solution serait de modifier extraire de sorte lorsqu’un élément
est défilé toute la file est passée vers l’avant.

 Si on ignore la possibilité d’un Underflow (file vide) l’opération s’écrit


x=F[0];
for (i=0; i<=ar-1; i++) F[i]= F[i+1];
ar=ar-1;

 Remarque : on n’a pas besoin dans ce cas de préciser la tête, elle est toujours au
début de la file

 Inconvénient : lorsqu’on a un tableau de grande taille, extraire un élément


nécessite le déplacement de tous les éléments du tableau.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


161
Les opérations de base sur la File
 une seconde solution consiste à voir la FILE comme un ensemble circulaire d’éléments
F[0], F[1], F[2], …. F[n-1], F[0]

E indice=4 E E E E
D D D av=3
D D av=3 av=3

C av=2 C av=2 H indice=2


G indice=1
G
F indice=0 F F
F indice=0

inserer(F) extraire(C) inserer(G) inserer(H)

 il n ’y a pas perte de place, on exploite tout le tableau. On aura un Overflow lorsque le


nombre d’élément égal à MAX.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


162
Les opérations de base sur la File
#include <stdio.h>
#define MAX 4
typedef struct{

int F[MAX];
int av;
int nb; // nombre d’élément dans la file

} TFile;

void initialiser(TFile *file) { file->av = 0; file->nb = 0; }

int filevide(TFile file) { return (file.nb == 0); }

int filepleine(TFile file) { return file.nb == MAX;}


Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
163
Les opérations de base sur la File
void enfiler(TFile *file,int x)

if (filepleine(*file)) printf("Overflow, file pleine\n");

else { int indice;

indice = (file->av + file->nb) % MAX;

file->F[indice] = x;

file->nb++;

}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
164
Les opérations de base sur la File
void defiler(TFile *file, int *obj)

if (filevide(*file)) printf("Underflow, file vide\n");

else { *obj =file->F[file->av];


file->av++;
if (file->av == MAX) file->av =0;
file->nb--;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


165
- 2ème partie : Représentation dynamique -

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


166
Représentation chainée (par pointeurs)
 Identiquement aux piles, cette structure est basée sur les listes
chaînées.

 Les éléments de la file sont chaînés entre eux.

 Chaque élément de la file pointera vers l'élément suivant.

 La récupération (extraction) des données sera faite dans l'ordre


d'insertion

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


167
Représentation chainée (par pointeurs)
 L’implémentation d’une file est la même qu’une liste simplement chaînée avec la
règle suivante :

L'ajout d'un élément se fera à la fin (queue, arrière) de la liste (File) et le


retrait d'un élément se fera au début (avant, tête) de la liste (File)

Extraction
30 15 6 2 Insertion
debut fin

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


168
Représentation
 La structure de la file
 Nous allons créer une file d'entiers (int)
 notre file sera basée sur une liste chaînée (simple)
 On suppose qu’un élément de la file est déclarée de la
façon suivante :

typedef struct element {

int info; /*La donnée que notre file stockera */


struct element * suivant; /*Pointeur vers l'élément suivant */

} Element;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


169
Représentation
 Pour avoir le contrôle de la file, il est préférable de sauvegarder ces éléments :
• l’adresse du premier élément : Correspond au début de la file et il permet de
réaliser l'opération de suppression des données Element *debut

• l’adresse du dernier élément : correspond à la fin de la file et il permet de réaliser


l'opération d’insertion des données Element *fin

• le nombre d'éléments : int taille


 On suppose que la File est déclarée de la façon suivante :

typedef struct {

Element * debut; /*Pointeur vers le premier élément */


Element * fin; /*Pointeur vers le dernier élément */
int taille; /* la taille de la file , ce champ est facultatif*/
} File;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


170
Opération de base sur les Files
 Initialisation
Prototype de la fonction : File * initialisation (File *F);

 Cette opération doit être faite avant toute autre opération sur la File.

 Elle initialise le pointeur debut et fin avec le pointeur NULL, et la taille avec la valeur 0.

Fonction
File * initialisation (File * F) {
F->debut = NULL;
F->fin = NULL;
F->taille = 0;
return F;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


171
Opération de base sur les Files
 Insertion d'un nouvel élément (Enfiler)

Prototype de la fonction :
La fonction renvoie un pointeur de type File.

File * enfiler(File * F, int donnee);

Algorithme de la fonction :
 Déclaration d'élément(s) à insérer.
 Allocation de la mémoire pour le nouvel élément.
 Remplir le contenu du champ de données.
 Mettre à jour des pointeurs
 Mettre à jour la taille de la file.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


172
Opération de base sur les Files
 Insertion d'un nouvel élément (Enfiler)

fin
debut Nouveau_Element
(2) donnee
donnee donnee donnee donnee (1) suivant
suivant suivant suivant suivant
NULL

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


173
Opération de base sur les Files
 Insertion d'un nouvel élément (Enfiler)
File * enfiler(File * F, int donnee) {

Element *nouveau_element;
nouveau_element=AllouerNoued();
nouveau_element->info= donnee;

if (F->fin==NULL) { F->fin = nouveau_element;


F->debut = nouveau_element;}

else { F->fin->suivant = nouveau_element;


F->fin = nouveau_element; }

F->taille++;
return F;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


174
Opération de base sur les Files
 Suppression d'un élément (Défiler)
Pour supprimer l'élément de la file, il faut tout simplement
supprimer l'élément vers lequel pointe le pointeur debut
Cette opération ne permet pas de récupérer la donnée au
début de la file, mais seulement de la supprimer.

Algorithme de la fonction :
 le pointeur supp_elem contiendra l'adresse du 1er élément (debut)
 le pointeur debut pointera vers le 2ème élément (après la
suppression du 1er élément, le 2ème sera au début de la file)
 la taille de la file sera décrémentée d'un élément

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


175
Opération de base sur les Files
 Suppression d'un élément (Défiler)

debut fin
(2)

donnee donnee donnee donnee


suivant suivant suivant suivant
NULL
(1)

Elem_supp

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


176
Opération de base sur les Files
 Suppression d'un élément (Défiler)
La fonction renvoie un pointeur de type File.

File * defiler (File * F) {

if (F->debut==NULL) return F;

else { Element * elem_supp;

elem_supp= F->debut;

if (F->taille == 1) {F->debut=NULL ; F->fin=NULL; }

else F->debut = F->debut->suivant;

free (elem_supp);

F->taille--; return F };

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


177
Opération de base sur les Files
 Affichage de la file

Algorithme de la fonction
 il faut se positionner au debut de la file
 En utilisant le pointeur suivant de chaque élément, la file est
parcourue du debut vers la fin
 La condition d'arrêt est donnée par la taille de la file
Fonction :
void affiche (File * F) {
Element *courant; int i;
courant = F->debut;
for(i=1;i<=(F->taille);i++) {
printf(" %d\n", courant->info);
courant = courant->suivant; }
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
178
Opération de base sur les Files
 Vider la file

 Il s'agit d’une fonction permettant d'effacer la File

Algorithme de la fonction

Tant que le pointeur fin n'est pas NULL

Effacer le premier élément de la file

Fonction :

File * file_clear(File *F) { while (F->fin != NULL) F=defiler(F); return F; }

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


179
Exemple d’application
 On veut gérer les queues en face des guichets d’une agence bancaire.
 L’agence contient 4 guichets qui rendent 5 services différents S1, S2, S3, S4,
S5; chaque service prend un certain temps d’exécution T1, T2, T3, T4, T5.

G1
G2

G3 G4

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 180


Exemple d’application
 Pour augmenter la rentabilité et sauver le temps des clients de la banque,
chaque nouveau client arrivant à l’agence doit être affecté à la queue la plus
petite en temps d’attente en faisant la comparaison des temps d’attente des 4
queues en face des 4 guichets.

 Pour cela on va utiliser les variables globales suivantes :


S1  3 minutes #define T1 3
S2  7 minutes #define T2 7
SERVICES : S3  10 minutes #define T3 10
S4  12 minutes #define T4 12
S5  15 minutes #define T5 15
 Q1 : Donner les déclarations nécessaires pour manipuler ce problème
 Q2 : Ecrire une fonction int service_temps_exec(Client C) qui prend en
paramètre un client et rend comme résultat le temps d’exécution du service
choisi.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 181


Exemple d’application
 Q3 : Ecrire une fonction File * eval_temps_attente(File * F) qui prend en
paramètre les 4 queues et rend comme résultat la queue qui présente le temps
d’attente minimum.
 Q4 : Enfiler consiste à prendre en paramètre un nouveau client nv et la file F
qui présente le temps d’attente minimum.
File * enfiler(File * F, Client nv)
 Q5 : Ecrire une fonction défiler qui prend en paramètre un guichet et défile le
client qui vient d’être servi.
File * defiler (File * F)
 Q6 : La fonction imprimer_ticket du client dans laquelle on va indiquer les
informations suivantes : son code et le nombre de personne qui le précède et le
temps d’attente avant de se rendre au guichet(temps d'attente minimum).
void imprimer_ticket (File * F, Client C)

 Q7 : Ecrire un programme principal main() qui fait appelle à l’ensemble des


fonctions, et qui consiste à appeler la fonction eval_temps_attente pour enfiler
le nouveau client au guichet qui présente le temps d’attente minimum.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 182


Exemple d’application
#include <stdio.h>

#define T1 3
#define T2 7
#define T3 10
#define T4 12
#define T5 15

typedef struct {
int code;
int type_serv;

}Client;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 183


Exemple d’application
typedef struct element {
Client cl; /*La donnée que notre file stockera */
struct element * suivant; /*Pointeur vers l'élément suivant */

}Element;

typedef struct {

Element * debut; /*Pointeur vers le premier élément */


Element * fin; /*Pointeur vers le dernier élément */

int taille; /* le nombre de personne en queue */


int temps_att; /* le temps d’attente total calculé pour la queue*/

} File;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 184


Exemple d’application
Client lire_client()

{ Client C;
printf("donner le code : ");
scanf("%d",&C.code);
do{
printf("donner le service dont tu as besoin {1,2,3,4,5} : ");
scanf("%d",&C.type_serv);
}while((C.type_serv<1)||(C.type_serv>5));

return C;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 185


Récapitulatif : Pile vs File
Pile File
Les objets sont insérés et supprimés à la même Les objets sont insérés et retirés de 2 extrémités
extrémité. différentes.

Dans les piles, un seul pointeur est utilisé. Il Dans les files, deux pointeurs différents sont
pointe vers le haut de la pile. utilisés pour les extrémités; la tète et la fin.

Dans les piles, le dernier objet inséré est le Dans les files, l’objet inséré en premier est le
premier à sortir. premier qui sera supprimé.

Les piles suivent l’ordre Last In First Out (LIFO) Les files suivent l’ordre First In First Out (FIFO)

Les opérations de pile s’appellent Empiler et Les opérations de file sont appelées Enfiler et
Dépiler. Défiler.
Les piles sont visualisées sous forme de Les files sont visualisées sous forme de
collections verticales. collections horizontales.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données


186
Chapitre 5 : Les arbres

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 187


1. Définitions
 Un arbre est une collection d’éléments de même type.

 La représentation d’un arbre en informatique se fait à l’envers : la racine se trouve


en haut et les branches se développe vers le bas.

 Chaque éléments (non racine) a exactement un seul parents.

 Un arbre, appelé aussi arbre N-aire, chaque nœud possède au maximum N nœuds.

66 66

21 70 50 21 70 50

32 43 88 32 43 88

Un arbre 3-aire Ce n’ai pas un arbre

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 188


1. Définitions
 Un arbre est constitué d’un nœud particulier appelé racine et d’une suite ordonnée
de sous-arbres A1, A2, …, Ap disjoints de la racine.

 Un arbre contient donc au moins un nœud : sa racine. Tous les autres nœuds
suivent directement ou indirectement la racine.
 Un sous arbre est un arbre.

 Exemple : 66
 La racine de cet arbre contient 66 Sous arbre
 Il est constitué de trois sous-arbres
 A1 : de racine 21, est réduit à 21 21 70 50

 A2 : de racine 70, contient 70 et 32


 A3 : de racine 50, contient 50, 43 et 88 32 43 88

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 189


1. Définitions
 les fils d’un nœud sont les racines de ses sous-arbres.
 une feuille d’un arbre est un nœud sans fils (qui n’a pas de suivant); 21, 32,43 et 88
sont des feuilles.
 Une branche est un chemin qui rejoint deux nœuds.
 la hauteur d’un nœud est égale au nombre de branches le séparant de la feuille la
plus éloignée plus un.
 la hauteur d’un arbre vaut la hauteur
de la racine.
Racine

Hauteur de l’arbre = 2+1=3


66
 La hauteur d’un arbre réduit à une
racine(un seul nœud) a une hauteur 1. Branche

21 70
50 Sous arbre

32 43 88 Feuille

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 190


2. Construction d'un arbre par un tableau
♦ Chaque nœud de notre exemple possède au plus trois nœuds fils.

♦ On construit un tableau à deux dimensions où chaque indice représente un


nœud.

♦ Pour connaître les suivants de chaque nœud, il suffit de voir leur indice
dans les cases ad-hoc du tableau.

♦ L’absence d’un nœud suivant est représenté par la valeur -1.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 191


2. Construction d'un arbre par un tableau

66
Numéro [0] [1] [2] [3] [4] [5] [6]
Valeur 66 21 70 50 32 43 88

21 70 50 Suivant1 1 -1 4 5 -1 -1 -1
Suivant2 2 -1 -1 -1 -1
-1 -1 -1
Suivant3 3 -1 -1 6 -1 -1 -1
32 43 88

♦ Cette construction est compliquée à gérer, et de ce fait, elle n’est pas très utilisée.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 192


3. Construction d'un arbre par une liste
chaînée
♦ Chaque nœud de notre exemple possède au plus trois nœuds fils.

66 ● ● ●

null null null 70 null null 50 ● null ●


21 ●

32 null null null 43 null null null 88 null null null

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 193


3. Construction d'un arbre par une liste
chaînée
♦ Les éléments de l’arbre sont dispersés dans la mémoire.
♦ Il suffit de connaitre l’adresse de la racine pour accéder aux différents éléments
de l’arbre.
♦ Un nœud pouvant référencer jusqu’à 3 nœuds suivants : 3 attributs gauche,
milieu et droite .

typedef struct Noeud {


int valeur;
struct Nœud * gauche;
struct Nœud * milieu;
struct Nœud * droit;
} NoeudEntier;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 194


4. Les principaux types d’arbres
♦ Arbres binaires(AB) : Cas particulier des arbres.
♦ Arbres binaires de recherche(ABR) : Cas particulier des arbres binaires.
♦ Arbres binaire de recherche équilibrés(ABRE) :
Cas particulier des arbres binaires de recherche et,
la différence de hauteur entre sous arbre gauche et sous arbre droit est < 2.

66 66

66
21 69
21 69

21 50
19 20 67 90
19 20 90

88 43 43 89
5 7 5 7

AB ABR ABR équilibré


Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 195
5. Arbres binaires
♦ Un arbre binaire est un arbre 2-aire : chaque nœud possède 0, 1 ou 2 suivants.
♦ Chaque arbre binaire peut posséder un arbre binaire droit et arbre binaire gauche
dont la racine est respectivement son fils droit et son fils gauche.
♦ Pour coder un arbre binaire, on fait correspondre à chaque nœud :
 une structure contenant la donnée et deux adresses, une 5
adresse pour chacun des deux nœuds fils .

 avec la convention qu’une adresse nulle indique un arbre


binaire vide . 9 2

 mémoriser l’adresse de la racine pour pouvoir accéder à


touts les éléments de l’arbre. 7 4 3

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 196


5. Arbres binaires

typedef struct noeud { 5


int valeur;
● ●
struct noeud * sag; arbre
struct noeud * sad;
} Abre;

Arbre * ar; 9 2
● ● NULL ●

7 4 3
NULL NULL NULL NULL NULL NULL

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 197


6. Les parcours d’arbre
♦ Il existe 2 types de parcours des valeurs d’un arbre : parcours en profondeur et
parcours en largeur.

1. Parcours en profondeur
♦ Pour ce type de parcours; on distingue entre 3 algorithmes récursifs simple permettent le
parcours en profondeur d’un arbre binaire : préfixé, infixé et postfixé.

♦ Tous les nœuds de l’arbre sont atteints branche par branche dans toute leur profondeur.

N°1 N°5 N°8

N°2 N°6 N°4 N°7 N°4 N°7

N°3 N°8 N°2 N°6 N°8 N°3 N°5 N°6


N°7

N°4 N°5 N°1 N°3 N°1 N°2

Parcours préfixé Parcours infixé Parcours suffixé ou post fixé

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 198


6. Les parcours d’arbre
parcours préfixé : le traitement de la racine se fait avant la visite des sous
arbres

void parcoursPrefixe(Arbre *ar) {


printf("%d ", ar->valeur); //traitement racine

if (ar->sag !=NULL) parcoursPrefixe(ar->sag); // appel récursive sag

if (ar->sad !=NULL) parcoursPrefixe(ar->sad); // appel récursive sad


} 5

Le parcours préfixé donne : 5 9 7 4 2 3 9 2

7 4 3

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 199


6. Les parcours d’arbre
parcours infixé : le traitement de la racine se fait entre les deux visites des
sous arbres

void parcoursInfixe(Arbre *ar) {


if (ar->sag !=NULL) parcoursInfixe(ar->sag); // appel récursive sag

printf("%d ", ar->valeur); //traitement racine

if (ar->sad !=NULL) parcoursInfixe(ar->sad); // appel récursive sad


} 5

Le parcours infixé donne : 7 9 4 5 2 3 9 2

7 4 3

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 200


6. Les parcours d’arbre
parcours postfixé (suffixé) : le traitement de la racine se fait après la visite
des sous arbres

void parcoursPostfixe(Arbre *ar) {


if (ar->sag !=NULL) parcoursPostfixe(ar->sag); // appel récursive sag

if (ar->sad !=NULL) parcoursPostfixe(ar->sad); // appel récursive sad

printf("%d ", ar->valeur); //traitement racine


} 5

Le parcours postfixé donne : 7 4 9 3 2 5 9 2

7 4 3

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 201


6. Les parcours d’arbre
2. Parcours en largeur
♦ Tous les nœuds de l’arbre sont atteints depuis la racine, puis couche par
couche de gauche à droit.
♦ Pour écrire cette méthode, il faut introduire une liste d’arbres où seront
stockés les nœuds au fur et à mesure de leur passage.
♦ Il faut ajouter en tête et retirer en queue : une file (FIFO) aurait même
suffit.
N°1

N°2 N°3

N°4 N°5 N°6 N°7

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 202


7. Arbre binaire de recherche
♦ Un arbre binaire de recherche (ABR), appelé aussi arbre binaire ordonné,
est un arbre tel que la valeur de chaque nœud est supérieure à celle du
sous arbre gauche et inférieure à celle du sous arbre droit.
♦ selon la mise en œuvre de l'ABR, on pourra interdire ou non des clés de
valeur égale.

55
typedef struct noeud {
int valeur;
struct noeud * fg; 40 60
struct noeud * fd;
} Arbre;
22 48 57 78
Arbre * ar;

33

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 203


7. Arbre binaire de recherche
 Initialiser l’ABR
♦ Cette fonction initialise les valeurs de la structure représentant l'arbre
pointé par a, afin que celui-ci soit vide : mettre le pointeur sur la racine
égal à NULL.

Arbre * initialiser(Arbre *a) {


a = NULL;
return a;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 204


7. Arbre binaire de recherche
 Préparer un nœud
♦ Cette fonction permet d’allouer de l’espace mémoire pour un nœud de l’arbre
avant de l’insérer et de remplir le champs de donnée.
♦ Initialiser le pointeur fg et fd par NULL.
Arbre * preparerNoeud(int v) {
Arbre * n;
n=(Arbre *)malloc(sizeof(Arbre));;
if (n==NULL) {printf("Memoire insuffisante\n"); exit(-1);}
else{ n->valeur=v;
n->fg=NULL;
n->fd=NULL;
return n; }
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 205
7. Arbre binaire de recherche
 Ajouter un nœud
Fonction ajoute la valeur v dans l'arbre pointé par a.

♦ Parcourir l'arbre à partir de la racine pour descendre jusqu'à l'endroit où


sera inséré le nœud.
♦ On prendra à gauche si à la valeur du nœud à insérer est inférieure à la
valeur du nœud visité.
♦ On prendra à droite si à la valeur du nœud à insérer est supérieure à la
valeur du nœud visité.
♦ On arrête la descente quand le fils gauche ou droit choisi pour descendre
vaut NULL. La valeur v est alors inséré à ce niveau.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 206


7. Arbre binaire de recherche
 Ajouter un nœud
Fonction ajoute la valeur v dans l'arbre pointé par a.
void ajouterNoeud(Arbre **a, int v) {
if (*a == NULL) { *a = preparerNoeud(v); }
if (v < (*a)-> valeur) ajouterNoeud(&((*a)->fg),v);
if (v > (*a)-> valeur) ajouterNoeud(&((*a)->fd),v);
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 207


7. Arbre binaire de recherche
 Suppression d’un nœud N
♦ Il y a trois cas possibles :
 Le nœud est terminal (feuille)
 Le nœud a un seul descendant
 Le nœud a deux descendants

♦ Pour le dernier cas on remplace le nœud par :


1. Le nœud le plus à droit de son arbre gauche, ou
Le nœud le plus à gauche de son arbre droit.
2. Puis on applique à nouveau la procédure de suppression
au nœud N, qui est maintenant une feuille ou
un nœud avec un seul fils.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 208


12
7. Arbre binaire de recherche 5 15

Suppression : le nœud de valeur 12 3 7 14 23


12
12 10 le nœud le
4 15 2 plus à droit
4 9 de l’arbre
3 5 14 23 gauche
3 5 8 11
le nœud le plus à gauche de
2 l’arbre droit 10
2
14
5 15
4 15
4 3 7 14 23

3 5 3 5 23
2 9
2 2 8 11

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 209


7. Arbre binaire de recherche
 Suppression d’un nœud
Fonction supprime le nœud de valeur x dans un arbre dont la racine est pointé
par a.

void Supprimer(Arbre **a, int x) { //recherche du nœud à supprimer


if (x< (*a)-> valeur) Supprimer(&((*a)->fg),x);
else if (x> (*a)->valeur) Supprimer(&((*a)->fd),x);
else { // a pointe vers le nœud à supprimer
Arbre *q=*a;
if (q->fd == NULL) *a=q->fg;
else if (q->fg == NULL) *a=q->fd;
else // deux fils
{ Remplacer_Gauche(&q);}
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 210


7. Arbre binaire de recherche
 Suppression d’un nœud
Remplacer le nœud pointé par q par le nœud le plus à droit de son sous arbre
gauche.

void Remplcer_Gauche(Arbre ** q) { Arbre *R,*S;


R=(*q)->fg;
S=*q;

while (R->fd!=NULL) {S=R; R=R->fd;}

(*q)->valeur=R->valeur;

if (R->fg!=NULL) S->fd=R->fg;
else S->fd=NULL;
free(R);
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 211


8. Exemple d’application 7
main() {
Arbre *racine; 4 9
racine=initialiser(racine); //7 4 9 3 2 5
ajouterNoeud(&racine, 7) ; parcoursPrefixe : 7 4 3 2 5 9
ajouterNoeud(&racine, 4) ; parcoursInfixe : 2 3 4 5 7 9
3 5
ajouterNoeud(&racine, 9) ; parcoursPostfixe : 2 3 5 4 9 7
ajouterNoeud(&racine, 3) ;
ajouterNoeud(&racine, 2) ;
ajouterNoeud(&racine, 5) ;
printf(" parcoursPrefixe : "); 2
parcoursPrefixe(racine); printf("\n");
printf(" parcoursInfixe : "); 5
parcoursInfixe(racine); printf("\n");
printf(" parcoursPostfixe : ");
parcoursPostfixe(racine); printf("\n"); parcoursPrefixe : 5 4 3 2 9 4 9
Supprimer(&racine,7) ;
printf(" parcoursPrefixe Apres la suppression :\n");
3
parcoursPrefixe(racine); printf("\n");
return 0;
}
2

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 212

Vous aimerez peut-être aussi