Vous êtes sur la page 1sur 6

Chapitre 4 (Atelier de programmation) :

Les listes chaînées


I. Définitions

Une liste chaînée est une structure comportant des champs contenant des données et un
pointeur vers une structure de même type. Une liste chaînée est ainsi une suite finie
(éventuellement vide) d’éléments de même type repérés selon leur rang dans la liste.
Données
Données Données
Pointeur vers NULL
Pointeur vers Pointeur vers
l’élément
l’élément l’élément
suivant
suivant suivant

II. Caractéristiques d’une liste chaînée


 Les éléments de la liste, appelés nœuds ou maillons, ne sont pas rangés les uns à
côté des autres en mémoire (contrairement aux éléments d’un tableau).
 On dispose d’un pointeur de tête qui contient l’adresse du premier élément de la
liste. Cette dernière – c’est-à-dire l’adresse du premier élément -- ne doit pas être
perdue, car si c’est le cas, les nœuds associés à la liste ne seront plus accessibles.
 Le dernier nœud ne pointe vers rien, il est nécessaire de renseigner son pointeur
avec la valeur NULL.

Inconvénient :
Contrairement au tableau, pour accéder à un élément il faut parcourir la liste.

Avantage :
- Pour déplacer un élément (Ajout, Suppression), il suffit de modifier ses liens et non
effectuer des décalages comme dans le cas d’un tableau.
- L’espace mémoire occupée par une liste chaînée est dynamiquement alloué. Il
pourra ainsi être libéré en cours d’exécution (moyennant la fonction dédiée free).
Ceci n’est pas le cas d’un tableau qui est statiquement alloué et qui ne peut donc pas
être libéré jusqu’à la fin de l’exécution du programme.

III. Création d’une liste chaînée

III.1. Déclaration

Pour créer une liste chaînée en langage C, il s'agit dans un premier temps de définir la
structure de données, ainsi qu'un pointeur vers une structure du type de celle définie
précédemment, afin de pointer vers la tête de la liste, c'est-à-dire le premier élément.

Syntaxe :
struct <Nom_ Maillon>
{ // Déclaration des champs du maillon
// Pointeur sur l’élément suivant
};

-1-
Exemple : Liste chaînée d’entiers

struct Maillon
{ int valeur ;
struct Maillon *suivant ;
};
typedef struct Maillon ListeEntier;
ListeEntier *L ;

15 10 22 6
L

III.2. Création d’une liste vide

Pour créer une liste vide, il suffit d’affecter la valeur NULL à la variable de type
"pointeur sur Liste" : L = NULL ;

III.3. Création d’une liste contenant un seul élément

ListeEntier *L, *p;

p=(ListeEntier*)malloc(sizeof(ListeEntier));
printf ("Entrer un entier \n");
scanf ("%d", &(p->valeur));
p->suivant=NULL;
L=p;

Remarque : Afin d’accéder aux champs de la cellule pointée par L, nous utilisons
donc l’écriture suivante : L->champ. Dans le cas de ListeEntier, deux champs existent
à savoir valeur et suivant.
Supposons que cette cellule contienne une structure d et x est un des champs de d.
Pour y accéder, il faut utiliser l’écriture suivante : L->d.x.

IV. Ajout d’un élément

L’opération ajout, appelée aussi insertion, peut être effectuée de différentes


manières dont les plus utilisées sont :
 l’ajout en tête de liste, et
 l’ajout en fin de liste.

-2-
IV.1 Ajout d’un élément en tête de liste

Version 1 : Version 2 :

void AjoutDebut(ListeEntier **L) ListeEntier* AjoutDebut(ListeEntier *L)


{ {
ListeEntier *p; ListeEntier *p;
p=(ListeEntier*)malloc(sizeof(ListeEntier)); p=(ListeEntier*)malloc(sizeof(ListeEntier));
printf("Donner un entier : "); printf("Donner un entier : ");
scanf("%d", &(p->valeur)); scanf("%d", &(p->valeur));
p->suivant=*L; p->suivant=L;
*L=p; L=p;
} return L;
}

IV.2 Ajout d’un élément en fin de liste

Version 1 : Version 2 :

void AjoutFin(ListeEntier **L) ListeEntier* AjoutFin(ListeEntier *L)


{ {
ListeEntier *p, *l; ListeEntier *p, *l;
p=(ListeEntier*)malloc(sizeof(ListeEntier)); p=(ListeEntier*)malloc(sizeof(ListeEntier));
printf("Donner un entier : "); printf("Donner un entier : ");
scanf("%d", &(p->valeur)); scanf("%d", &(p->valeur));
p->suivant=NULL; p->suivant=NULL;
if(*L==NULL) if(L==NULL)
*L=p; L=p;
else else
{
l=*L; {
while(l->suivant!=NULL) l=L;
l=l->suivant; while(l->suivant!=NULL)
l->suivant=p; l=l->suivant;
} l->suivant=p;
} }
return L ;
}
Les fonctions d’ajout d’un élément au début de la liste ou à sa fin peuvent ainsi être
appelée afin de charger une liste. Le programme suivant illustre cela :
void main ()
{
ListeEntier *L ;
int n;
printf ("Nombre d’éléments à insérer :" ) ;
scanf ("%d", &n) ;
for (i = 1 ; i<=n ; i++)
AjoutDebut(&L);
}

-3-
Application : Ecrire une fonction permettant d’insérer un entier x dans une liste d’entiers tout
en respectant l’ordre croissant des éléments de cette liste (à distinguer les différents cas
d’insertion de x : au début, à la fin, ou au « milieu »).

V. Recherche d’un élément

La fonction suivante retourne 1 si l’élément se trouve dans la liste et 0 sinon.

int Recherche(ListeEntier *L, int val)


{
ListeEntier *p;
int trouve=0;
p=L ;
while (p!=NULL && trouve==0)
{
if (pvaleur==val)
trouve=1;
p=psuivant;
}
return(trouve);
}
Application : Reprendre la fonction précédente sans utiliser la variable trouve sachant que la
fonction renvoie un pointeur sur la cellule contenant la valeur recherchée ou renvoie NULL
sinon.

VI. Suppression d’un élément

Version 1 : Version 2 :

void Supprimer(ListeEntier **L, int val) ListeEntier* Supprimer (ListeEntier *L, int
{ val){
ListeEntier *p, *q; ListeEntier *p, *q;
p=*L; p=L;
while(p!=NULL && pvaleur!=val) while(p!=NULL && pvaleur!=val)
p=psuivant; p=psuivant;
if(p!=NULL) if(p!=NULL)
{ {
if(p==(*L)) if(p==L)
(*L)=(*L)->suivant; L=L->suivant;
else else
{ {
q=*L; q=L;
while(q->suivant!=p) while(q->suivant!=p)
q=q->suivant; q=q->suivant;
q->suivant=p->suivant; q->suivant=p->suivant;
} }
free(p); free(p);
} }
} return L;
}

-4-
Application : Reprendre les deux versions précédentes en réalisant un seul parcours de la liste
et non deux.

VII. Affichage d’une liste chaînée :

void AffichListe(ListeEntier *L)


{
ListeEntier *p;
for(p=L; p!=NULL && p->suivant; p=p->suivant)
printf(" %d - ", p->valeur);

printf(" %d ", p->valeur);


}

VIII. Libération d’une liste chaînée

void LibererListe(ListeEntier *L)


{
ListeEntier *p;
while(L !=NULL){
p=L;
L=L->suiv;
free(p);}
}

Exercices
Exercice 1 :

Ecrire une fonction permettant de retourner l’adresse de la cellule où se trouve la première


occurrence d’une valeur recherchée dans la liste si elle existe. La fonction retourne NULL
sinon.

Exercice 2 :

Ecrire une fonction qui permet de supprimer la cellule contenant la première occurrence d’une
valeur donnée. Cette fonction utilisera la fonction développée dans la question précédente.

Exercice 3 :

Ecrire une fonction permettant de charger au clavier un ensemble d’entiers et de les stocker
sans redondance et dans l’ordre décroissant dans une liste chaînée.

Exercice 4 :

Le but de cet exercice est d’écrire un programme c qui permet de mémoriser dans une liste
simplement chaînée les informations relatives aux N joueurs d’une équipe de rugby et de
traiter ses informations. Un joueur est caractérisé par son nom, son prénom et son poids.

-5-
Chaque joueur a un numéro de poste (1 à 15) qui détermine son rôle dans l’équipe (le numéro
1 est pilier gauche, le numéro 2 talonneur, etc.).
1. Définir les structures de données adéquates permettant de représenter un joueur et
une liste simplement chaînée de joueurs.
2. Écrire une fonction qui permet de remplir et retourner dans une variable structurée
les informations relatives à un joueur.
3. Écrire une procédure qui permet d’insérer un joueur dans la liste de manière à
garder la liste triée selon l’ordre croissant des numéros de poste.
4. Écrire une fonction qui permet de chercher un joueur à travers son numéro de
poste et de renvoyer son adresse.
5. Écrire une procédure qui permet de supprimer un joueur connaissant son numéro
de poste.
6. Écrire une procédure qui permet d’afficher le poids, le numéro de poste, le nom et
le prénom du joueur le plus lourd de l’équipe d’une part et le poids moyen des
joueurs d’autre part.
7. En se basant sur les fonctions et les procédures précédentes, écrire un programme
principal permettant :
 De construire une équipe de 15 joueurs
 D’afficher les informations relatives au joueur le plus lourd de l’équipe et
le poids moyen des joueurs.

Exercice 5 :

Soit une bibliothèque donnée. On se propose de stocker les principales informations relatives
aux livres contenus dans cette bibliothèque. Chaque livre sera caractérisé par les informations
suivantes :
 Le titre du livre ;
 L’auteur du livre (où son premier auteur s’il y en a plusieurs) : son nom et son
prénom ;
 La publication du livre : date de la publication (mois et année) ainsi que le nom de
l’éditeur et le numéro de l’édition.

1) Déclarer une structure contenant les informations relatives à l’auteur du livre, et une
autre contenant les informations relatives à la publication du livre.
2) Déclarer une structure contenant toutes les informations relatives à un livre donné
sachant que les livres seront gérés dans une liste chaînée simple.
3) Ecrire un algorithme permettant :
 De stocker les informations relatives aux différents livres que contient la
bibliothèque. La saisie s’arrête dès que la chaîne O est insérée dans le champ
relatif au titre du livre.
 D’afficher toutes les informations relatives aux livres, une fois la saisie
terminée.
 De chercher toutes les informations relatives à un livre dont le titre sera saisi
au clavier par l’utilisateur.
 De chercher toutes les informations relatives aux livres écrits par un auteur
dont le nom et le prénom seront saisis au clavier par l’utilisateur.
 De chercher toutes les informations relatives aux livres dont le nom de
l’éditeur sera saisi au clavier par l’utilisateur.
 De trouver les livres ayant le maximum nombre d’édition.

-6-

Vous aimerez peut-être aussi