Vous êtes sur la page 1sur 74

COURS DE STRUCTURE DES

DONNEES LINEAIRES

Préparé par

Diomède NZISABIRA

ISCAM 2021
I. Rappel sur les structures
II. Listes
1. Les listes simplement chaînées ;
2. Les listes doublement chaînées.
III. Les piles
IV. Les files

Structures de Données Linéaires Diomède NZISABIRA


I. RAPPEL SUR LES STRUCTURES

Une structure est un type composite, caractérisé par


un nom et des membres (composants ou champs).

Une structure peut être composée par de types


simples et/ou de types structurés.

Définition d’une structure


Syntaxe :
Struct NomStr
{
Type1 nomV1 ;
Type2 nomV2 ;
….
Typen nomVn ;
};

Avec :

Structures de Données Linéaires Diomède NZISABIRA


NomStr : le nom de la structure. Il respecte les
mêmes conventions de nommage que pour les noms
des variables.
Typei : type de champs. C’est l’un des types connu
en C
nomVi : noms des champs

Déclaration d’une variable de type structure


Etant donné NomStr, un nom d’une structure, la
déclaration d’une variable pouvant contenir les
éléments de type Nomstr se fait comme suit :
Struct NomStr NomVS ;
Avec NomVS : le nom de la variable structure.
La déclaration d’une variable structure peut
également se faire au moment de la définition de la
structure.

Structures de Données Linéaires Diomède NZISABIRA


Dans ce cas, la syntaxe est la suivante :
struct NomStr
{
Type1 nomV1 ;
Type2 nomV2 ;
….
Typen nomVn ;
} NomVS ;

Exemple :
Définir une structure appelée Point et caractérisée
par : une abscisse, abs, et une ordonnée, ord, toutes
les deux de type entier.

Struct Point
{
1
int abs ;
int ord ;
};

Structures de Données Linéaires Diomède NZISABIRA


Déclarer deux variables A, P, destinées à contenir des
points.

Struct Point A ;
2
Struct Point A, P ;
Struct Point P ;

Rmq : 1 et 2 peuvent être remplacés par :

Struct Point
{
int abs ;
int ord ;
} A,P;
Afin d’alléger les notations, il peut être nécessaire de
créer des synonymes. Pour ce faire, on utilise le mot
clé typedef.

Structures de Données Linéaires Diomède NZISABIRA


Sa syntaxe est la suivante :

1. Typedef struct AncNomStr


{
Type1 nomV1 ;
Type2 nomV2 ;
….
Typen nomVn ;
}NouvNomStr ;
Avec
AncNomStr : Ancien nom de la structure
NouvNomStr : Nouveau nom de la structure. Il est
aussi considéré comme le synonyme de l’ancien nom
ou bien l’alias.
Typei, nomvi : voir les explications précédentes

Structures de Données Linéaires Diomède NZISABIRA


2. Struct NomStr
{
Type1 nomV1 ;
Type2 nomV2 ;
….
Typen nomVn ;

};

Typedef struct Nomstr NouvNom ;

 1 et 2 donnent le même résultat final.


 Lorsque l’on oublie de mettre le mot clé typedef
au moment de la définition de la structure suivie
de la création d’un alias (voir 1), le nouveau nom
(NouvNom) devient une variable au lieu du
synonyme.

Structures de Données Linéaires Diomède NZISABIRA


Exemple :

Etant donné le point précédemment défini, on peut


créer le synonyme de la façon suivante :

Typedef struct Point point ;

Typedef struct Point Akaburungu ;

Après ces deux instructions, point et akaburungu


désignent exactement la même chose soit : struct Point.

Ainsi les écritures suivantes s’équivalent :

Struct Point A,B ;

point A,B ;

akaburungu A,B ;

Exercices

1. Ecrire un programme permettant de créer un point


coloré. Celui-ci est caractérisé par :

Abs et Ord : de type réel

Structures de Données Linéaires Diomède NZISABIRA


Couleur : un tableau de 10 caractères qui est
destiné à contenir le nom de la couleur du point
d’abscisse Abs et d’ordonnée Ord.

NB :
On écrira simplement les instructions pour
définir le point et déclarer trois points.

2. De ce qui précède, créer synonyme de point :


PointColore. Déclarer un tableau de 15 point
colorés en utilisant ce synonyme.
Typedef struct Etudiant
{
char Nom[15] ;
char Pren[15] ;
int Mat ;
} Etudiant ;
Etudiant E ;
Etudiant T [20] ;

10

Structures de Données Linéaires Diomède NZISABIRA


Accès aux champs (membres) d’une structure
Pour Accéder aux champs de structures on utilisera
les opérateurs d’accès suivants :
.

L’opérateur d’accès point (.) est utilisé lorsque l’on
est en face d’une simple variable tandis que
l’opérateur d’accès flèche () s’utilise si l’on est
en face d’un pointeur sur structure.
Pour utiliser l’opérateur d’accès (.) sur les
pointeurs sur structures, il faudra faire précéder le
pointeur concerné par *

Exemples :

Etant donné le point coloré précédemment défini,


réserver un emplacement mémoire P pour contenir
un point coloré.

11

Structures de Données Linéaires Diomède NZISABIRA


Remplir les champs de ce point coloré. Créer un
point coloré Q ayant les mêmes caractéristiques
que le point P.
Créer un pointeur ptr sur un point coloré. Faire
pointer ptr sur P. Afficher le point coloré P.
Solution :
PointColore P ;
P.Abs= 12.5 ;
P.Ord= 7 ;
strcpy(P.T, « Jaune ») ; /* Permet de copier
« jaune » dans le tableau T (champ T) du point P*/

PointColore Q ;
Q.Abs=P.Abs ;
Q.Ord=P.Ord ;
Strcpy(Q.T,P.T) ;

PointColore* ptr ;
ptr= &P ; /*Après cette instruction ptr pointe sur
P*/
12

Structures de Données Linéaires Diomède NZISABIRA


printf(‘’ Les caractéristiques du point P sont :’’) ;
printf(‘’%f\t%f\t%s’’, Abs, Ord, T) ;/* Abs, Ord,
T n’existent pas en dehors d’un point*/
printf(‘’%f\t%f\t%s’’, P.Abs, P.Ord, P.T) ;
ou
printf(‘’%f\t%f\t%s’’, ptrAbs, ptrOrd,
ptrT) ;
ou
printf(‘’%f\t%f\t%s’’, (*ptr).Abs, (*ptr).Ord,
(*ptr).T) ;

Rmq :
ptr Abs =18 ; Cette instruction permet de mettre
la valeur 18 dans le champ Abs du point pointé par
ptr. C'est-à-dire le point P.
Cette instruction aura le même effet que
l’instruction P.Abs=18 ;
Ainsi, on peut déduire qu’il est possible de changer
(ou d’accéder à) la valeur d’un champ d’une
structure en utilisant un pointeur.
13

Structures de Données Linéaires Diomède NZISABIRA


Structure ayant un/des champ(s) structuré(s) :
définition et accès aux membres

Exemple :

Ecrire les instructions nécessaires pour définir un étudiant.


Celui-ci est caractérisé par :

 Un nom et un prénom : des tableaux de 20


caractères chacun ;
 Un numéro matricule : un entier ; et
 Une date de Naissance.

La date de Naissance est à son tour composé par : le jour, le


mois et l’année qui sont tous des entiers.

Déclarer et remplir une variable E de type étudiant. Afficher


les informations de cet étudiant.

14

Structures de Données Linéaires Diomède NZISABIRA


Solution
Solution :
typedef struct etu
typedef struct Date
{
{
char nom[20] ;
int jr ;
char pren[20] ;
int Mat ; int mois ;

DatN D ; int An ;

}Etudiant ; }DatN ;

typedef struct Date typedef struct etu


{ {
int jr ; char nom[20] ;
int mois ; char pren[20] ;
int An ; int Mat ;
}DatN ;
DatN D ;
Etudiant E ;
}Etudiant ;
strcpy(E.nom, « Amsini ») ;

strcpy(E.pren, « Christophe ») ;
15

Structures de Données Linéaires Diomède NZISABIRA


E.Mat=12 ;

E.DatN.jr=25 ;

E.D.jr=25 ;

E.D.mois=10 ;

E.D.An=1990 ;

printf (« Les informations de l’étudiant précédent sont les


suivantes : ») ;

printf (« Nom : %s\t Prénom : %s\t Matricule : %d\n Date


de Naissance : %d/%d/%d\n », E.nom, E.pren, E.Mat,
E.D.jr, E.D.mois, E.D.An) ;

16

Structures de Données Linéaires Diomède NZISABIRA


Exercices :

1. Ecrire un programme permettant de :


a. Définir un point de l’espace. Celui-ci est caractérisé
par :
 L’abscisse et l’ordonné de type entier ;
 Un nom : un tableau de 10 caractères.
b. Créer une courbe de 50 points.
c. Afficher les coordonnées des 50 points.

2. Ecrire un programme permettant de définir un point


caractérisé par trois coordonnées de types entier
chacune. Créer deux points. Créer un troisième point
ayant pour coordonnées la somme des coordonnées des
points précédents.

3. Ecrire un programme permettant de créer une ligne


droite. Sachant que celle-ci est caractérisée par ses deux
points qu’elle lie. Chacun possédant les coordonnées de
type réel.

17

Structures de Données Linéaires Diomède NZISABIRA


4. On désire gérer un ensemble de livres d’une
bibliothèque.
Chaque livre est caractérisé par :
 Titre : tableau de 100 caractères ;
 Auteur : tableau de 20 caractères ;
 Année d’édition composé par le jour, le mois et
l’année de type entier tous les trois ;
 Maison d’édition : tableau de 40 caractères ;
 ISBN : un entier.

On vous demande de :

a. Définir un livre ;
b. Créer un tableau de 10 livres de telle sorte que deux
livres ne puissent jamais avoir le même ISBN ;
c. Afficher tous les livres ;
d. Afficher tous les livres ayant pour auteur « Ali » ;
e. Afficher tous les livres édités en 1980 ;
f. Afficher le nombre de livres édités chez ULBU 2nd
Form company.
18

Structures de Données Linéaires Diomède NZISABIRA


Exercice 3 :
#include<stdio.h>
typedef struct point
{
float abs,ord ;
} Point
typedef struct ligne
{
Point A ;
Point B ;
} Ligne ;
void main()
{
Ligne L ;
printf(« donner les coordonnées du premier point de cette
ligne : ») ;
scanf(« %f%f »,&L.A.abs,&L.A.ord) ;
printf(« donner les coordonnées du deuxième point de cette
ligne : ») ;
scanf(« %f%f »,&L.B.abs,&L.B.ord) ;
/*Affichage des deux points*/

19

Structures de Données Linéaires Diomède NZISABIRA


printf(« Les coordonnées des deux points de cette ligne sont
les suivantes:\n » ;
printf(” A(%f,%f) ;B(%f,%f)”,L.A.abs,L.A.ord,L.B.abs,L.B.
ord) ;
}

20

Structures de Données Linéaires Diomède NZISABIRA


II. LISTES

II.1 Définition

Une liste est une structure de données composée essentiellement par deux catégories de champs :
une partie pour contenir la/les valeur(s) et une ou plusieurs partie pour indiquer où se trouve les
autres éléments. Cette/ces dernière(s) partie(s) contien(nen)t une/des adresses d’une /de liste(s) et
nous permet(tent) de distinguer deux catégories de listes : listes simplement chaînées et listes
doublement chaînées.

II.2 Les listes simplement chaînées

Une liste est simplement chaînée, lorsqu’elle est composée d’une partie pour contenir la valeur et
d’une partie pour contenir l’adresse du suivant. La partie pour contenir la valeur peut être composite.
Ces deux parties sont aussi appelées champs.

Remarque

Le nombre total de champs dans une liste simplement


chaînées est toujours >= à 2.

21

Structures de Données Linéaires Diomède NZISABIRA


2.1 Définition

NB : Pour cette section comme pour les suivantes, nous allons travailler sur les entiers pour les
différents exemples.

typedef struct liste


{
int Val ; /*contenir la valeur ou l’entier*/
struct liste*suiv ; /*contenir l’adresse du suivant*/
}Liste ;

2.2 Quelques opérations sur les listes simplement


chaînées

a. Déclaration d’une variable de type liste

Val suiv
Liste A ;
A
Liste A ; struct liste A ;

Liste B, C ; /*permet de déclarer deux variables de type Liste chacune*/

b. Accès aux champs d’une liste

L’accès aux champs d’une liste se fait comme celui sur les structures. Ainsi, on
utilisera les opérateurs point (.) et flèche ()

22

Structures de Données Linéaires Diomède NZISABIRA


c. Insertion d’un élément en-tête de liste : fonction InserTete

1. Liste*InserTete(Liste*Deb, int v)
2. {
Val suiv
3. Liste*Q ;
4. Q=(Liste*)malloc(sizeof(Liste)); Q
5. Qval=v ;/*mettre la valeur v dans le champ val de Q*/
6. Qsuiv=Deb ;
7. Deb=Q ;
8. return(Deb) ;/*return(Q) ;*/
9. }

1DEF
Deb 125 NULL

12
1DEF 1AEB

1AEB
12

Q 1DEF

23

Structures de Données Linéaires Diomède NZISABIRA


d. La recherche du dernier élément de la liste :
fonction Dernier
1. Liste*Dernier(Liste*Deb)
2. {
3. Liste*Last ;
4. Last=Deb;
5. if(Last!=NULL)/*si liste pas vide*/
6. {
7. while( Lastsuiv !=NULL)
8. {
9. Last=Lastsuiv ;
10.}
11.}
12.return(Last) ;
13.}

e. L’Insertion d’un élément en queue de la liste :


fonction InserQueue

Liste* InserQueue (Liste*Deb, int v)

Liste*Last ,*Q;
Last=Dernier(Deb);
Q=(liste*)malloc(sizeof(Liste));
Qval=V;
Qsuiv=NULL;
24

Structures de Données Linéaires Diomède NZISABIRA


Last=Q;
if(Last!=NULL) /* si le dernier existe*/
Lastsuiv=Q;
Else
Deb=Q;
Return(Q);/*return (Last)*/
return(Deb);
}
10 129 123
Deb

Last

Q 14

NB :

Lorsque la liste est vide, l’insertion en tête et l’insertion en


queue donne le même résultat (la liste sera composée par
l’élément inséré).

25

Structures de Données Linéaires Diomède NZISABIRA


Lors des différents chaînages ou autres traitements, il
faudra éviter de faire référence aux différents champs
pour un pointeur NULL

f. L’Insertion d’un élément au milieu d’une liste:


fonction InserMilieu

Pour insérer un élément au milieu d’une liste, il faut


connaître la position après laquelle l’élément sera inséré.

Celle-ci peut être donnée ou recherchée. Dans ce qui suit


nous allons illustrer les deux cas.

 Insertion d’un élément dans la liste après une position


donnée

Liste *InserMilieu(Liste*Deb, Liste*Prec, int V)


{
Liste*Q ;
Q=(Liste*)malloc(sizeof(Liste));
Qval=v;
26

Structures de Données Linéaires Diomède NZISABIRA


Qsuiv=Precsuiv;
Precsuiv=Q;
return(Deb);
}
10 129 123
Deb

Prec
145

Remarque:

La fonction ci-dessus n’est valable que si Prec est


différent de NULL et bien sûr si c’est une partie de la
liste d’en-tête Deb.

 Insertion d’un élément dans la liste après une position


à rechercher

27

Structures de Données Linéaires Diomède NZISABIRA


Insérer la valeur 12 après la première occurrence de 21 dans
une liste d’entiers ayant pour tête Deb.

Pour faire un tel exercice, il faudra d’abord chercher la


position de 21 dans la liste avant l’insertion.

Pour notre cas nous utilisons une fonction de recherche de


cette position.

Liste*Recherche (Liste*Deb)
{
Liste*Q ;
Q=Deb ;
while(Q !=NULL&&Qval!=21)
Q=Qsuiv;
return(Q);
}

Liste*InsertMilieu(Liste*Deb, int v)

28

Structures de Données Linéaires Diomède NZISABIRA


{
Liste*Prec ;
Prec=Recherche(Deb) ; /*recherche de la position où
apparaît la valeur 21 dans la liste Deb*/
/*Nous nous convenons que la valeur v sera insérée au début
si 21 ne figure pas dans la liste*/
if (Prec==NULL)
Deb=InserTete(Deb,v) ;
Else
if(Precsuiv==NULL)
Deb=InserQueue(Deb,v) ;

Else
Deb=InserMilieu(Deb,Prec,v) ;
return(Deb) ;
}

29

Structures de Données Linéaires Diomède NZISABIRA


g. Suppression d’un élément en tête de liste
Liste* SupprimerEnTete(Liste*Deb)
{
Liste*Q ;
Q=Deb ;
if(Deb !=NULL)
{
Deb=Debsuiv ;
free (Q) ;
}
return(Deb);

h. Recherche du précédent : fonction Precedent


Liste*Precedent(Liste*Deb, Liste*P)
{
Liste*Prec ;
Prec=Deb ;
if(Prec !=NULL)
30

Structures de Données Linéaires Diomède NZISABIRA


{
While(Precsuiv !=P)
Prec=Precsuiv ;
}
return(Prec) ;
}

i. Suppression d’un élément en queue d’une liste

Pour pouvoir supprimer un élément en queue d’une


liste ou se trouvant au milieu d’une liste, il est
indispensable de connaître la position qui précède celle
où se trouve l’élément à supprimer.

Liste* SupprimerEnQueue(Liste*Deb)
{
Liste*Der,*Prec;
Der=Dernier(Deb) ; /*recherche du dernier
élément*/
if(Der ==Deb)/*si la liste contient un seul élément*/
31

Structures de Données Linéaires Diomède NZISABIRA


Deb=SupprimerEnTete(Deb) ;
Else
{
Prec=Precedent(Deb,Der) ;/*Recherche de la
position qui précède le dernier*/
Precsuiv=NULL ; /*Prec devient le nouveau
dernier*/
free(Der) ;
}
return(Deb) ;

Exercices

Ex1 :

Ecrire un programme permettant de :

a. Définir une liste d’entiers ;


b. Créer une liste de 10 valeurs ;
c. Afficher les valeurs de la liste ;
d. Afficher toutes les valeurs de la liste qui sont paires ;
32

Structures de Données Linéaires Diomède NZISABIRA


e. Afficher les éléments de la liste supérieurs à la
moyenne ;
f. Supprimer la première occurrence de 25 ;
g. Afficher la nouvelle liste.

Ex2 :

Ecrire un programme permettant de définir une liste de


réels.

a. Créer une liste de N éléments, N étant un entier>0 ;


b. Afficher tous les éléments de la liste ;
c. Calculer la moyenne des éléments de cette liste ;
d. Afficher le nombre de valeur > à la moyenne ;
e. Créer une liste composée par tous les éléments de la
liste précédente qui sont inférieurs à la moyenne.

Ex3 :

Ecrire un programme permettant de :


33

Structures de Données Linéaires Diomède NZISABIRA


a. Créer une liste L1 de N entiers pairs chacun ;
b. Créer une liste L2 de M entiers impairs chacun ;
c. Afficher les éléments des deux listes ;
d. Fusionner les deux listes pour trouver une liste L3 de
telle sorte que les éléments de L3 soient alternativement
pairs et impairs, partout où c’est possible ;
e. Afficher la liste L3.

Ex4 :

Ecrire un programme permettant de créer un point. Celui-ci


est caractérisé par deux coordonnées de type réel.

a. Créer un tableau de 10 points ;


b. Du tableau précédent, créer une liste qui contient
l’ensemble de ces points ;
c. Supprimer le tableau après création de cette liste ;
d. Afficher les éléments de la liste.

Ex5 :

Ecrire un programme permettant de :

34

Structures de Données Linéaires Diomède NZISABIRA


a. Créer une liste de notes d’un étudiant. Chaque note est
caractérisée par une valeur obtenue, celle-ci appartient
dans l’intervalle [0,20], et le coefficient appartenant
dans l’intervalle [1,9]. Le nombre de notes (cours) est
fourni par un utilisateur ;
b. Calculer la moyenne générale de l’étudiant(e) ;
c. Afficher toutes les notes en dessous de la moyenne ;
d. Afficher le nombre de notes supérieures à la moyenne
e. Afficher toutes les notes
f. Afficher toutes les notes en commençant par la
dernière.

Ex6 :
Ecrire un programme permettant de :
1. Définir une liste d’ordinateurs. Chaque ordinateur
possède les caractéristiques suivantes :
 Sa capacité de type entier ;
 Sa vitesse de type entier ;
 Sa fréquence de type entier ;

35

Structures de Données Linéaires Diomède NZISABIRA


 Son système d’exploitation qui est un tableau de
10 caractères ;
 Le nombre de périphériques de type entier.
Celui-ci doit être supérieur à 3 et ne doit pas
dépasser 6 ; ainsi que
 Son coût. Il est compris entre 800 et 1300.
Notez qu’un ordinateur possède également sa
marque et un numéro de série unique.
2. Créer une liste de N ordinateurs, N étant un entier >
à4;
3. Afficher tous les ordinateurs de marque DELL ;
4. Afficher le nombre d’ordinateurs répondant à un
critère donné par un utilisateur ;
5. Supprimer tous les ordinateurs qui coûtent moins de
1000 $;
6. Afficher la liste des ordinateurs après la suppression ;
7. Afficher les ordinateurs en commençant par le
dernier de la liste ;
8. Insérer un ordinateur après le premier ordinateur
ayant un nombre de périphériques > 4. Si aucun
36

Structures de Données Linéaires Diomède NZISABIRA


ordinateur ne possède plus de 4 périphériques,
l’insertion se fera en-tête de la liste ;
9. Trier les ordinateurs par prix croissant ;
10. Afficher les ordinateurs après le tri.

NB : Pour le point 4 de cet exercice, il faudra donner un


critère qui correspond à l’égalité d’un des caractéristiques
de cette machine.

37

Structures de Données Linéaires Diomède NZISABIRA


II.2 Les listes doublement chaînées.

Une liste est doublement chaînée, quand elle possède deux champs d’adresse: l’un pour indiquer
l’adresse du précédent et l’autre pour indiquer l’adresse du suivant. Elle doit également avoir un ou
plusieurs champs caractéristiques des valeurs à mettre dans la liste.
On notera que, le précédent du premier et le suivant du dernier n’existent pas. Ces deux champs
contiendront la valeur : NULL.
Au cours de ce chapitre, nous apprendrons à définir une liste doublement chaînée et à manipuler
(faire quelques opérations sur) de telles listes.
Pour des questions de simplicité, on fera ces illustrations sur des listes d’entiers, les autres cas feront
objet des exercices.

II.2.1 Définition

typedef struct liste


typedef struct liste
{
{
struct liste*prec ; struct liste*prec ;
int val ; struct liste*suiv ;
struct liste*suiv ; int val ;
}liste ; }liste ;

typedef struct liste


{
int val ;
struct liste*prec ;
struct liste*suiv ;
}liste ;

Comme le montre les notations ci-dessus, l’ordre des champs importe peu. L’important est que les
champs caractéristiques aux éléments de la liste soient tous présents et que leurs types soient
clairement indiqués.

Les définitions précédentes permettent de créer un type appelé liste et ayant pour caractéristique les
trois champs indiqués. L’accès aux champs d’une telle structure est la même que pour une liste
simplement chaînée. C’est-à dire que l’on utilise les mêmes types d’opérateurs et leur
fonctionnement ne change pas.
38

Structures de Données Linéaires Diomède NZISABIRA


II.2.2 Quelques opérations sur les listes doublement chaînées

a. Création d’une liste vide

Pour créer une liste vide, il suffit de déclarer un pointeur sur la liste, après sa définition, et
d’initialiser le pointeur à NULL ;

Ex : liste*Deb ;

Deb=NULL ;

Ces opérations peuvent se faire à l’intérieur d’une fonction.

Liste*CreerListeVide() Liste*CreerListeVide()

{ {
liste*Deb ;
Deb=NULL ; return(NULL);
return(Deb) ;
}
}
b. Insertion d’un élément au sein d’une liste doublement chaînée

Insérer un élément dans une liste, peut se faire en-tête, au milieu ou en queue.

39

Structures de Données Linéaires Diomède NZISABIRA


 Insertion en-tête : InserTete
liste*InserTete (liste*Deb, int V)
{
liste*Q ;
Q=(liste*)malloc(sizeof(liste));
Qsuiv=Deb;
Qprec=NULL;
Qval=V;
if(Deb!=NULL)
{
Debprec=Q;
}
Deb=Q;
return(Deb);/*return(Q);*/

40

Structures de Données Linéaires Diomède NZISABIRA


 La recherché du dernier élément de la liste : Dernier

Rappelons qu’un élément d’une liste est dernier s’il n’a pas de suivant (le champ destiné à
contenir l’adresse du suivant contient : NULL).

Liste*Dernier (liste*Deb)
{
Liste*Q ;
Q=Deb ;
while(Q !=NULL &&Qsuiv!=NULL)
Q=Qsuiv ; //Passer au suivant
return(Q) ;
}

ou

liste*Dernier (liste*Deb)
{
Liste*Q ;
Q=Deb ;
if(Q !=NULL)/*si la liste contient au moins un élément*/
while(Qsuiv!=NULL) //tant que le champ suiv ne contient pas NULL
Q=Qsuiv ; //Passer au suivant
return(Q) ;
}

 Insertion d’un élément à la fin d’une liste : InserQueue

liste*InserQueue(liste*Deb, int v)
{
Liste*Der,*Q ;
/*Recherche du dernier*/
Der=Dernier(Deb) ;
if(Der==NULL)
Deb=InserTete(Deb,v) ;
else
{
Q=(liste*)malloc(sizeof(liste));
Qval=v;
Qsuiv=NULL;
Qprec=Der;
Dersuiv=Q;
}
return(Deb);
}

41

Structures de Données Linéaires Diomède NZISABIRA


 Insertion d’un élément au milieu d’une liste : InserMilieu
Insérer un élément au milieu d’une liste revient à mettre l’élément en question avant ou après une
position donnée dans la liste.
Dans ce qui suit, nous allons définir les deux variantes d’insertion au milieu.
Pour cela, nous utiliserons la fonction InserMilieu1 pour insérer au milieu avant une position
indiquée et la fonction inserMilieu2 pour l’autre cas.
1. liste*InserMilieu1(liste*T,liste*Suivant, int v)
2. {
3. liste*Q ,*P;
4. Q=(liste*)malloc(sizeof(liste));
5. Qsuiv=Suivant;
6. Qprec=Suivantprec;
7. Qval=v;
8. P=Suivantprec
9. Psuiv=Q;
10. Suivantprec=Q;
11. return(T);
12. }

10 NULL

Suivant
123
4
P

Q
T

42

Structures de Données Linéaires Diomède NZISABIRA


Remarque :

Cette fonction n’est valide que si la liste n’est pas vide et que T est différent de suivant. T étant
considéré comme la tête de liste.

liste*InserMilieu2(liste*T,liste*Pr, int v)

liste*Q ,*P;
Q=(liste*)malloc(sizeof(liste));
Qsuiv=Prsuiv;
Qprec=Pr;
Qval=v;
P=Prsuiv ;
Prsuiv=Q;
Pprec=Q;
return(T);
}

Remarque :

Cette fonction n’est valide que si la liste n’est pas vide et que Pr est élément du milieu de la
liste. T étant considéré comme la tête de liste.

c. Suppression d’un élément d’une liste doublement chaînée

Comme pour l’insertion, la suppression peut se faire en-tête, au milieu ou en queue

43

Structures de Données Linéaires Diomède NZISABIRA


 Suppression d’un élément en-tête de liste :SuppressionTete

liste*SuppressionTete(liste*Deb)

liste*Q ;

Q=Deb ;

if(Q !=NULL)

Deb=Debsuiv ;

Debprec=NULL;

free(Q) ;

return(Deb) ;

44

Structures de Données Linéaires Diomède NZISABIRA


 Suppression d’un élément en queue de liste :SuppressionQueue

liste* SuppressionQueue (liste*Deb)

liste*Q,*P ;

Q=Dernier(Deb) ;

if(Q !=NULL) /*si la liste contient au moins 1 élément*/

if(Q==Deb)

Deb=NULL;

else

P=Qprec;

Psuiv=NULL;

free(Q) ;

return(Deb) ;

45

Structures de Données Linéaires Diomède NZISABIRA


 Suppression d’un élément au milieu d’une liste :SuppressionMilieu

liste* SuppressionMilieu (liste*Deb, liste*S)

liste*Q,*P ;

if(S ==Deb) /*Suppression en tête*/

Deb=SuppressionTete(Deb) ;

else

if(Ssuiv==NULL)

Deb= SuppressionQueue(Deb) ;

else

Q=Sprec;

P=Ssuiv;

Qsuiv=Ssuiv;

Pprec=Q;

free(S) ;

return(Deb) ;

46

Structures de Données Linéaires Diomède NZISABIRA


d. Affichage des éléments d’une liste
Il est possible d’afficher les éléments d’une liste en commençant par la tête de liste ou la fin
de liste.

 Affichage en commençant par la tête de liste : Affiche


void Affiche(liste*T)
{
liste*P ;
P=T ;
while(P !=NULL)
{
printf(« %d\t »,Pval) ;

P=Psuiv ;

47

Structures de Données Linéaires Diomède NZISABIRA


 Affichage en commençant par le dernier de la liste : AfficheInverse
void AfficheInverse(liste*T)
{
liste*P ;
P=Dernier(T) ;
while(P !=NULL)
{
printf(« %d\t »,Pval) ;

P=Pprec ;

Exercices

Ex1 :

Ecrire un programme permettant de :

a. Définir une liste doublement chaînée de réels ;


b. Créer une liste de 10 éléments ;
c. Afficher les éléments de cette liste ;
d. Supprimer la 3ème valeur de la liste ;
e. Afficher la nouvelle liste.

48

Structures de Données Linéaires Diomède NZISABIRA


Ex2 :

Ecrire un programme permettant de créer une liste doublement chaînée d’entiers. Définir
les fonctions permettant de :
a. Insérer un élément en-tête de liste ;
b. Afficher les éléments d’une liste ;
c. Compter le nombre de fois qu’un élément donné apparaît dans la liste ;
d. Saisir un entier >0 ;
Utiliser ces fonctions pour créer une liste de N éléments. Afficher le nombre de fois
qu’apparaît la valeur 123 et afficher les éléments de cette liste.

Ex3 :
Ecrire un programme permettant de :
a. Définir une liste de caractères ;
b. Créer une liste de N éléments, N étant un entier positif fourni par un utilisateur. Les
caractères de cette liste doivent être ordonnées de manière croissante au moment de la
saisie et ces caractères sont supposés être des minuscules;
c. Afficher les éléments de cette liste en commençant par le dernier de la liste ;
d. Insérer la lettre ‘g’ dans la liste, de telle sorte qu’elle reste ordonnée ;
e. Supprimer toutes les occurrences de la lettre ‘s’ ;
f. Afficher la nouvelle liste.

Ex4 :
Ecrire un programme permettant de :
a. Définir une liste de cours. Chaque cours possède un intitulé : tableau de 10
caractères, un volume horaire et un coefficient de type entier.
Le coefficient ne doit pas dépasser 9 et est >0 ;
b. Créer une liste de 15 cours ;
c. Afficher les volumes horaires de chaque cours ;
d. Changer le volume horaire du cours intitulé « Mode et système d’exploitation » pour
le rendre 45 ;
e. Insérer le cours intitulé « Audit Informatique » ayant un volume horaire de 45H et
un coefficient 3 dans la liste. Ce cours sera insérer immédiatement après le premier
cours ayant un volume horaire >45. Si aucun cours de la liste ne possède pas ce
volume horaire, il faudra alors l’insérer en tête de liste ;
49

Structures de Données Linéaires Diomède NZISABIRA


f. Afficher la nouvelle liste.

Ex5 :

ULBUMan est une société spécialisée dans la production et la vente de téléphones portables. Cette
société désire un petit programme pour gérer ses produits. Ainsi, on vous demande de :

a. Définir une liste doublement chaînée de téléphones portables. chaque téléphone est
caractérisé par :
 Sa marque : un tableau de 15 caractères ;
 Numéro de série : un entier>0 ;
 Date de fabrication et durée de vie qui sont toutes de type DATE. DATE est
composé par jr,mois, et an de type entier. L’année pour la durée de vie doit être
>à l’année de fabrication. La date de création de ULBUMan est : 3 mai 2000 ;
 Prix qui est de type entier et > 10.000 BIF.
b. Créer une liste de X téléphones. X étant un entier >0 ;
c. Afficher la liste de téléphones ;
d. Eclater la liste précédente en deux listes : une contenant la liste des téléphones ayant un prix
<60.000 et une autre contenant le reste ;
e. Afficher les deux nouvelles listes ;
f. Au sein d’une même fonction, supprimer tous les téléphones, des deux listes précédentes,
fabriqués en 2005 ;
g. Afficher ces nouvelles listes.

50

Structures de Données Linéaires Diomède NZISABIRA


III. Les piles
Une pile est une structure de données pour laquelle
l’insertion des éléments et/ou la suppression se fait
sur un même bout. Le principe de gestion de piles est
le LIFO (Last In First Out), c'est-à-dire que le
premier élément mis dans une pile sera servi (traité)
en dernier lieu. Au cours de ce chapitre, nous allons
définir une pile, puis nous passerons en revue des
principales opérations (traitements) sur les piles. Les
exemples illustratifs seront basés sur des piles
d’entiers.
1. Définition
Une pile peut être implémentée en utilisant la
notation tableaux (une structure statique ou
tableau) ou bien en utilisant une liste chaînée
(structure dynamique). La définition d’une pile en
utilisant une liste chaînée se fait comme déjà vu
pour les autres listes, à la seule différence que pour
le reste des opérations, l’insertion et/ou la
suppression se fera sur un même bout. Ainsi, si au
51

Structures de Données Linéaires Diomède NZISABIRA


moment de la création de la pile, on a utilisé
l’insertion en-tête, alors la suppression des
éléments pour cette pile se fera en-tête.
Par contre, si l’insertion s’est faite en queue alors
la suppression se fera en queue.
De même si l’insertion s’est faite au milieu alors la
suppression se fera au milieu.
a. Définition d’une pile en utilisant une liste
simplement chaînée.
typedef struct liste
{
int val ;
struct liste*suiv ;
}Pile ;

b. Définition d’une pile en utilisant un tableau


Pour ce cas, il nous faudra avoir trois éléments à
savoir : un nom du tableau, une variable entière
nous indiquant l’élément courant et une variable
entière nous indiquant le sommet.
52

Structures de Données Linéaires Diomède NZISABIRA


On se conviendra que le courant (qui indique la
position courante), va nous servir de parcourir le
tableau. On dira que la pile est vide si courant
contient 0 et que la pile est pleine si courant
contient la valeur de sommet.

typedef struct pile


{
int courant ;
int *Tab ;
int sommet ;

}Pile ;

2. Quelques opérations sur les piles

Que ça soit pour la représentation dynamique ou statique


des piles, toutes les opérations sur piles s’appuient sur deux
opérations particulières à savoir l’empilement et le
dépilement.

53

Structures de Données Linéaires Diomède NZISABIRA


Dans cette section nous allons détailler les principales
fonctions sur les piles. Les deux types de représentations
seront traités séparément.

a. Cas de représentation sous forme de liste


 Tester si une pile est vide : la fonction EstVide

Une pile est vide si elle ne contient aucun élément. Pour le


cas de cette fonction, nous retournerons la valeur 1 si la pile
est vide et 0 sinon.

int EstVide(Pile*P)
{
if(P==NULL)
return(1) ;
else
return(0) ;
}

54

Structures de Données Linéaires Diomède NZISABIRA


 L’empilement : fonction empiler

L’empilement consiste à ajouter un élément dans la pile.


Pour le cas de pile, on peut utiliser un passage par valeur ou
par adresse.

Dans le premier cas, il faudra retourner la pile et dans le


second cas on ne retourne rien.

Pile*Empiler(Pile*P, int V)
{
Pile*Q ;
Q=(Pile*)malloc(sizeof (Pile));
Qval=V;
Qsuiv=P;
P=Q;
return(P);/*return(Q) ;*/
}
Le cas précédent est un passage par valeur. En utilisant un
passage par adresse, la fonction précédente deviendra :

55

Structures de Données Linéaires Diomède NZISABIRA


void Empiler1(Pile**P, int V)
{
Pile*Q ,*T;
T=*P;
Q=(Pile*)malloc(sizeof (Pile));
Qval=V;
Qsuiv=T;
T=Q;
}
NB : Afin d’éviter que les deux fonctions portent le même
nom, nous ajoutons un 1, au nom de la dernière fonction.

Etant donné un pointeur Deb, déjà initialisé, sur Pile


l’utilisation des fonctions précédemment définies se fera
comme suit :

Deb=Empiler(Deb,V) ;
Empiler1(&Deb,V) ;

56

Structures de Données Linéaires Diomède NZISABIRA


Avec :
V : une variable entière contenant une valeur ou simplement
un entier quelconque.
D’où les notations suivantes sont correctes sous réserve que
les différentes variables existent et contiennent des valeurs.
Les deuxièmes paramètres doivent être de type entier.
Deb=Empiler(Deb,X) ;
Empiler1(&Deb,X) ;
Deb=Empiler(Deb,Y) ;
Empiler1(&Deb,Y) ;
Deb=Empiler(Deb,10) ;
Empiler1(&Deb,10) ;
Deb=Empiler(Deb,-15) ;
Empiler1(&Deb,-15) ;

 Le dépilement : fonction Depiler

Le dépilement consiste à enlever un élément d’une pile.


Cette opération n’est possible que si la pile contient au
moins un élément.

57

Structures de Données Linéaires Diomède NZISABIRA


Toute fonction de dépilement doit ramener l’élément dépilé.
C'est-à-dire celui qui se trouvait en-tête. Afin de
sauvegarder les changements opérés sur la pile il faut faire
un passage par adresse pour une telle fonction.

int Depiler(Pile**P)

int V ;

Pile*Q ;

Q=*P ;

*P=*Psuiv ;

V=Qval ;

free (Q) ;

return(V) ;

Remarque :
Cette fonction ne doit pas être appelée en lui fournissant une
Pile vide. Il faudra alors tester l’état de la pile avant l’appel
d’une telle fonction sous peine de voir le programme se
planter.

58

Structures de Données Linéaires Diomède NZISABIRA


 Affichage des éléments d’une pile : fonction
Affiche

Exemple d’une fonction d’affichage :


void Affiche(Pile**Q)
{
int V ;
Pile*P ;
P=*Q ;
printf(« les éléments de cette pile sont:\n » );
while(P !=NULL)/*Pile pas vide*/
{
V=Depiler(&P) ;
printf(« %d\t »,V) ;
}
/*******P est NULL*/
}
Afficher les éléments d’une pile revient à faire le dépilement
et bien sûr quelques fois à empiler une autre pile si l’on veut
sauvegarder les valeurs de l’ancienne.

59

Structures de Données Linéaires Diomède NZISABIRA


Pile* Affiche1(Pile**T)
{
Pile*P,*Q ;
int V ;
Q=NULL ;
P=*T ;
printf(« les éléments de cette pile sont:\n » );
while(P !=NULL)
{
V=Depiler(&P) ;
printf(« %d\t »,V) ;
/*Conservation des éléments de P*/
Q=Empiler(Q,V) ;
}
/*Reconstitution de P*/
While(Q !=NULL)
{
V=Depiler(&Q) ;
P=Empiler(P,V) ;
}
return(P) ;
}

/******************************************/

60

Structures de Données Linéaires Diomède NZISABIRA


b. Cas de représentation statique d’une pile

La représentation statique d’une pile est celle qui consiste à


implémenter une pile en utilisant un tableau. Dans ce qui
suit, nous allons détailler les principales fonctions de
traitement d’une telle pile.

Nous nous convenons que, pour les manipulations à venir


que la plus petite valeur de courant est : 0.

 Tester si une pile est vide : la fonction EstVide

Cette fonction retourne la valeur 1 si la pile est vide et 0


sinon.

Dire qu’une pile est vide, revient à vérifier si le contenu du


champ courant est égal à Zéro (0).

Rappelons que la définition de la structure pile est la


suivante :

61

Structures de Données Linéaires Diomède NZISABIRA


typedef struct pile
{
int courant ;
int *Tab ;
int sommet ;

}Pile ;

62

Structures de Données Linéaires Diomède NZISABIRA


int EstVide(Pile*P)
{
if(Pcourant==0)
return(1) ;
else
return(0) ;
}

 Créer une pile vide de N éléments

Pour créer une pile vide de N éléments, il suffit d’allouer un


emplacement mémoire de N éléments pour tab et de mettre
la valeur approprié dans le champ sommet et dans le champ
courant. De ce qui précède, nous voulons dire une pile
ayant la capacité de contenir N éléments.

63

Structures de Données Linéaires Diomède NZISABIRA


Pile*CreerPile( int N)
{
Pile*P ;
P=(Pile*)malloc(sizeof(Pile));
Psommet=N;
Pcourant=N-1;
Pcourant=0;
PTab=(int*)malloc(Psommet*sizeof(int));
/*PTab=(int*)malloc(N*sizeof(int));*/
return(P);
}

 Tester si une pile est pleine : EstPleine

Une telle pile est pleine lorsque le contenu du champ


sommet est égal à celui du champ courant. La fonction va
nous retourner 1 si la pile est pleine et 0 sinon.

int EstPleine(Pile*P)
{
if (Psommet==Pcourant)
return(1);
else
return(0);
}

64

Structures de Données Linéaires Diomède NZISABIRA


 L’empilement : fonction Empiler

Comme pour la représentation dynamique, l’empilement


consiste à ajouter un élément dans la pile. Cependant, pour
ce cas, il faut se rassurer si la pile n’est pas pleine avant
d’ajouter un nouvel élément.

Pile*Empiler(Pile*P, int V)
{
int ok;
ok =EstPleine(P) ;
if(ok==1)
printf(« Impossible d’ajouter un élément car elle est
pleine ») ;
else
{
PTab [Pcourant] =V;
Pcourant++;
}
return (P);
}

 Le dépilement : fonction Depiler

Comme pour la pile précédente, le dépilement consiste à


enlever un élément de la pile si celle-ci n’est pas vide.
65

Structures de Données Linéaires Diomède NZISABIRA


int Depiler(Pile**P)
{
int V,ok ;
ok=EstVide(*P);
if(ok==1)
{
printf(“impossible de dépiler car la pile est vide ») ;
return(-1) ;
}
else
{
*Pcourant--;
V=*PTab [*Pcourant];
return (V) ;
}
}

66

Structures de Données Linéaires Diomède NZISABIRA


Remarque :
Au moment de la définition de la fonction ci-dessus, nous
avons opté de retourner la valeur -1 si la pile est vide. Cela
suppose donc qu’aucune valeur de la pile ne doit être -1.

 Affichage des éléments d’une pile : fonction


Affiche

Pour afficher les éléments de la pile on devra utiliser la


fonction de dépilement.
void Affiche(Pile*P)
{
int V ;
if (EstVide(P)==0)
{
printf(« les éléments de cette pile sont:\n » );
/*Aussi longtemps qu’on n’a pas vidé la pile P*/
while(P !=NULL)
{
V=Depiler(&P) ;
printf(« %d\t »,V) ;
}
}
else
printf(« Il n’ y a pas d’éléments à afficher car la pile est
vide ») ;
}
67

Structures de Données Linéaires Diomède NZISABIRA


Exercices
Ex1
On désire gérer un ensemble de réels en utilisant une pile.
Pour cela, on vous demande de :
a. Définir cette pile ;
b. Créer une pile de capacité 10 et remplir cette pile ;
c. Afficher le contenu de cette pile ;
d. Afficher la somme des éléments de cette pile ;
e. Afficher la petite et la grande valeur de cette pile.
NB
Il faudra faire cet exercice de deux manières différentes : en
utilisant la représentation statique et la représentation
dynamique.
Ex2
Ecrire un programme permettant de :
1. Définir une pile de livres. Chaque livre possède un titre
et un nombre de pages >0 ;
2. Créer une pile de N éléments ;
3. Afficher tous les livres ayant un nombre de pages >
200 ;

68

Structures de Données Linéaires Diomède NZISABIRA


4. De la pile précédente extraire une pile composée par
tous les livres ayant un nombre de pages pair.
Ex3
Ecrire un programme permettant de gérer un ensemble
d’assiettes en utilisant une pile.
Chaque Assiette est caractérisée par :
 La couleur : un tableau de 5 éléments de type
caractère;
 La forme : un tableau de 10 caractères ;
 La capacité : entier>0.
On aimerait avec ce programme :
a. Créer une pile de N éléments, N entier>0 ;
b. Insérer une assiette avant une position quelconque en
partant du sommet ;
c. Afficher la pile ;
d. Supprimer une assiette dont le numéro est indiqué par
l’utilisateur. Le décompte commencera toujours par la
valeur au sommet ;
Ce programme devra se faire de deux manières : en
utilisant une structure statique et une structure
dynamique.

69

Structures de Données Linéaires Diomède NZISABIRA


IV. Les files
Une file est une structure de données obéissant au
principe du premier arrivé premier servi(FIFO).
Au cours de ce chapitre, nous apprendrons à
implémenter ce genre de structure ainsi que les
principales opérations y relatives. Les exemples
traités dans le cadre du cours seront basés sur les
entiers. D’autres types de données pourront être vus
dans les exercices de TD1 et de TP2.
1. Définition
typedef struct file
{
int val ;
struct file*suiv ;
}File ;
Comme le montre les instructions précédentes, nous voyons
qu’une file est semblable, du point de vue représentation, à
une liste chaînée. Seule le mode de gestion va être différent
pour les deux types de structures. On pourra

1
Travaux Dirigés

2
Travaux Pratiques
70

Structures de Données Linéaires Diomède NZISABIRA


indépendamment utiliser une liste simplement chaînée ou
doublement chaînée.

2. Quelques fonctions de traitement de files

A l’image de ce qui a été fait sur les piles, les opérations de


traitement (gestion) de files s’appuient essentiellement sur
l’enfilement et le défilement.

Afin de respecter le principe du FIFO, si l’enfilement se fait


en-tête alors, le défilement se fera en queue et inversement.

a. L’enfilement : fonction Enfiler

L’enfilement consiste à ajouter un élément dans une file.

File*Enfiler(File*F, int v)
{
File*P ;
P=(File*)malloc(sizeof(File));
Pval=V;
Psuiv=F;
F=P;
return(F);
71

Structures de Données Linéaires Diomède NZISABIRA


}

10 129
F

15

b. Recherche du premier à entrer dans la file : fonction


Recherche
File* Recherche (File*F)
{
File *P ;
P=F ;
while (P !=NULL&&Psuiv!=NULL)
{
P=Psuiv;
}
return(P);
}
c. La recherche du précédent : fonction Precedent

File*Precedent(File*P,file*K)
{
72

Structures de Données Linéaires Diomède NZISABIRA


file*F;
F=P;
While(F!=NULL&&Fsuiv!=K)
F=Fsuiv;
Return(F);
}

d. Défilement: fonction Defiler

Rappelons que le défilement consiste à enlever un élément


d’une file. Cela suppose que la file n’est pas vide. Il faudra
alors mettre des balises nécessaires pour éviter de faire un
défilement sur une file vide.

int Defiler(File**F)

File*Q ,*P;
int V ;
Q=Recherche(*F );/*premier venu*/
P=Precedent(*F,Q) ;
V=Qval ;
If(P !=NULL)
Psuiv=NULL;
free (Q) ;
73

Structures de Données Linéaires Diomède NZISABIRA


return(V) ;
}

NB :

Cette fonction est valide lorsque la file contient au moins


un élément et que l’enfilement s’est fait en tête.

Pour le cas où l’enfilement s’est fait en queue cette


fonction deviendrait :

int Defiler(File**F)
{
File*Q ;
int V ;
Q=*F ;
*F=(*F)->suiv ;
V=Qval ;
free (Q) ;
return(V) ;
}

74

Structures de Données Linéaires Diomède NZISABIRA

Vous aimerez peut-être aussi