Vous êtes sur la page 1sur 18

Les listes chanes

Par lexou

www.openclassrooms.com

Licence Creative Commons 6 2.0


Dernire mise jour le 24/08/2011

2/19

Sommaire
Sommaire ........................................................................................................................................... 2
Les listes chanes ............................................................................................................................ 3
Gnralits sur les listes chaines ................................................................................................................................... 3
Dclaration en C d'une liste chaine ................................................................................................................................. 5
Manipuler les listes chaines (1/2) .................................................................................................................................... 6
Ajouter un lment ...................................................................................................................................................................................................... 6

Exercices (1/2) .................................................................................................................................................................. 8


Manipuler les listes chaines (2/2) .................................................................................................................................. 10
Supprimer un lment en tte ................................................................................................................................................................................... 11
Supprimer un lment en fin de liste ......................................................................................................................................................................... 11
Rechercher un lment dans une liste ...................................................................................................................................................................... 12
Compter le nombre d'occurrences d'une valeur ........................................................................................................................................................ 12
Recherche du i-me lment .................................................................................................................................................................................... 13
Rcuprer la valeur d'un lment ............................................................................................................................................................................. 13
Compter le nombre d'lments d'une liste chan .................................................................................................................................................... 14
Effacer tous les lments ayant une certaine valeur ................................................................................................................................................. 14

Exercices (2/2) ................................................................................................................................................................ 15


Q.C.M. ............................................................................................................................................................................. 16
Partager ..................................................................................................................................................................................................................... 18

www.openclassrooms.com

Sommaire

3/19

Les listes chanes

Par

lexou

Mise jour : 24/08/2011

Bonjour tous et toutes.


Euh, un tutoriel sur les listes chanes ? C'est quoi a ?
Rassurez-vous : tout vous sera expliqu, depuis zro.
A qui s'adresse ce tutoriel ?

Il s'adresse toute personne ayant suivi les cours de M@teo jusqu'aux pointeurs. Ce tutoriel accompagn des exercices que je
vous proposerai sont mon avis un excellent entranement, en ce qui concerne les pointeurs, entre autres, mais fera appel
toutes vos connaissances du langage C.

Et la fin, que saurai-je faire ?

Le but de ce tutoriel est de vous initier aux listes chanes, une autre faon d'implmenter un conteneur, la plus courante tant
les tableaux. A la fin de ce cours, vous serez capables de coder votre propre bibliothque permettant la cration et la
manipulation de listes simplement chanes. Les listes doublement chaines seront introduites pour terminer afin que vous
puissiez amliorer votre bibliothque.

Je suis sr que vous tes prts : nous allons donc commencer !


Sommaire du tutoriel :

Gnralits sur les listes chaines


Dclaration en C d'une liste chaine
Manipuler les listes chaines (1/2)
Exercices (1/2)
Manipuler les listes chaines (2/2)
Exercices (2/2)
Q.C.M.

Gnralits sur les listes chaines


Lorsque vous crez un algorithme utilisant des conteneurs, il existe diffrentes manires de les implmenter, la faon la plus
courante tant les tableaux, que vous connaissez tous. Lorsque vous crez un tableau, les lments de celui-ci sont placs de
faon contigu en mmoire. Pour pouvoir le crer, il vous faut connatre sa taille. Si vous voulez supprimer un lment au milieu
du tableau, il vous faut recopier les lments temporairement, r-allouer de la mmoire pour le tableau, puis le remplir partir de
l'lment supprim. En bref, ce sont beaucoup de manipulations coteuses en ressources.
Une liste chane est diffrente dans le sens o les lments de votre liste sont rpartis dans la mmoire et relis entre eux par
des pointeurs. Vous pouvez ajouter et enlever des lments d'une liste chane n'importe quel endroit, n'importe quel instant,
sans devoir recrer la liste entire.
Nous allons essayer de voir ceci plus en dtail sur ces schmas :

www.openclassrooms.com

Les listes chanes

4/19

Vous avez sur ce schma la reprsentation que l'on pourrait faire d'un tableau et d'une liste chane. Chacune de ces
reprsentations possde ses avantages et inconvnients. C'est lors de l'criture de votre programme que vous devez vous poser
la question de savoir laquelle des deux mthodes est la plus intressante.
Dans un tableau, la taille est connue, l'adresse du premier lment aussi. Lorsque vous dclarez un tableau, la variable
contiendra l'adresse du premier lment de votre tableau.
Comme le stockage est contigu, et la taille de chacun des lments connue, il est possible d'atteindre directement la case i
d'un tableau.
Pour dclarer un tableau, il faut connatre sa taille.
Pour supprimer ou ajouter un lment un tableau, il faut crer un nouveau tableau et supprimer l'ancien. Ce n'est en
gnral pas visible par l'utilisateur, mais c'est ce que realloc va souvent faire. L'adresse du premier lment d'un
tableau peut changer aprs un realloc, ce qui est tout fait logique puisque realloc n'aura pas forcement la
possibilit de trouver en mmoire la place ncessaire et contigu pour allouer votre nouveau tableau. realloc va donc
chercher une place suffisante, recopier votre tableau, et supprimer l'ancien.

Dans une liste chane, la taille est inconnue au dpart, la liste peut avoir autant d'lments que votre mmoire le permet.
Il est en revanche impossible d'accder directement l'lment i de la liste chaine.
Pour ce faire, il vous faudra traverser les i-1 lments prcdents de la liste.
Pour dclarer une liste chane, il suffit de crer le pointeur qui va pointer sur le premier lment de votre liste chane,
aucune taille n'est donc spcifier.
Il est possible d'ajouter, de supprimer, d'intervertir des lments d'une liste chane sans avoir recrer la liste en entier,
mais en manipulant simplement leurs pointeurs.

Chaque lment d'une liste chane est compos de deux parties :


la valeur que vous voulez stocker,
l'adresse de l'lment suivant, s'il existe.
S'il n'y a plus d'lment suivant, alors l'adresse sera NULL, et dsignera le bout de la chane.
Voil deux schmas pour expliquer comment se passent l'ajout et la suppression d'un lment d'une liste chane. Remarquez le
symbole en bout de chane qui signifie que l'adresse de l'lment suivant ne pointe sur rien, c'est--dire sur NULL.

www.openclassrooms.com

Les listes chanes

5/19

Comme vous vous en doutez certainement maintenant, la liste chane est un type structur. Nous en avons termin avec ces
quelques gnralits, nous allons pouvoir passer la dfinition d'une structure de donnes nous permettant de crer cette
fameuse liste !
Vous pouvez essayer d'imaginer quoi va ressembler la structure liste_chainee : si vous avez compris le principe,
vous en tes capables. Je vous invite donc crire sur un papier vos ides que vous pourrez ensuite comparer au
rsultat que je vais fournir un peu plus bas !

Dclaration en C d'une liste chaine


Vous vous demandez srement de quel type sera l'lment de la liste chane. A ceci je ne peux rpondre que... vous de voir. En
effet, vous pouvez crer des listes chanes de n'importe quel type d'lments : entiers, caractres, structures, tableaux, voir
mme d'autres listes chanes... Il vous est mme possible de combiner plusieurs types dans une mme liste.
Allez : vous avez assez patient, voici la dclaration d'une liste simplement chane d'entiers :
Code : C
#include <stdlib.h>
typedef struct element element;
struct element
{
int val;
struct element *nxt;
};
typedef element* llist;

On cre le type element qui est une structure contenant un entier (val) et un pointeur sur lment (nxt), qui contiendra l'adresse
de l'lment suivant. Ensuite, il nous faut crer le type llist (pour linked list = liste chane) qui est en fait un pointeur sur le type
element. Lorsque nous allons dclarer la liste chane, nous devrons dclarer un pointeur sur element, l'initialiser NULL, pour
pouvoir ensuite allouer le premier lment. N'oubliez pas d'inclure stdlib.h afin de pouvoir utiliser la macro NULL. Comme vous
allez le constater, nous avons juste cre le type llist afin de simplifier la dclaration.
Voil comment dclarer une liste chane (vide pour l'instant) :
Code : C
#include <stdlib.h>

www.openclassrooms.com

Les listes chanes

6/19

typedef struct element element;


struct element
{
int val;
struct element *nxt;
};
typedef element* llist;

int main(int argc, char **argv)


{
/* Dclarons 3 listes chanes de faons diffrentes mais
quivalentes */
llist ma_liste1 = NULL;
element *ma_liste2 = NULL;
struct element *ma_liste3 = NULL;

return 0;

Il est important de toujours initialiser la liste chane NULL. Le cas chant, elle sera considre comme contenant au
moins un lment. C'est une erreur frquente. A garder en mmoire donc. De manire gnrale, il est plus sage de
toujours initialiser vos pointeurs.

Manipuler les listes chaines (1/2)


Maintenant que nous savons comment dclarer une liste chane, il serait intressant d'apprendre ajouter des lments dans
cette liste, ainsi que de lire ce qu'elle contient. C'est ce que nous allons tudier dans cette premire partie sur la manipulation des
listes chanes. Je vous invite essayer par vous-mmes de programmer ces quelques fonctions basiques permettant de
manipuler les listes. Dans tous les cas (ou presque), nous renverrons la nouvelle liste, c'est--dire un pointeur sur element
contenant l'adresse du premier lment de la liste.

Ajouter un lment
Lorsque nous voulons ajouter un lment dans une liste chane, il faut savoir o l'insrer. Les deux ajouts gnriques des listes
chanes sont les ajouts en tte, et les ajouts en fin de liste. Nous allons tudier ces deux moyens d'ajouter un lment une
liste.

Ajouter en tte
Lors d'un ajout en tte, nous allons crer un lment, lui assigner la valeur que l'on veut ajouter, puis pour terminer, raccorder cet
lment la liste passe en paramtre. Lors d'un ajout en tte, on devra donc assigner nxt l'adresse du premier lment de la
liste pass en paramtre. Visualisons tout ceci sur un schma :

Code : C

www.openclassrooms.com

Les listes chanes

7/19

llist ajouterEnTete(llist liste, int valeur)


{
/* On cre un nouvel lment */
element* nouvelElement = malloc(sizeof(element));
/* On assigne la valeur au nouvel lment */
nouvelElement->val = valeur;
*/

/* On assigne l'adresse de l'lment suivant au nouvel lment


nouvelElement->nxt = liste;

/* On retourne la nouvelle liste, i.e. le pointeur sur le


premier lment */
return nouvelElement;
}

C'est l'ajout le plus simple des deux. Il suffit de crer un nouvel lment puis de le relier au dbut de la liste originale. Si l'original
est , (vide) c'est NULL qui sera assigne au champ nxt du nouvel element. La liste contiendra dans ce cas-l un seul lment.

Ajouter en fin de liste


Cette fois-ci, c'est un peu plus compliqu. Il nous faut tout d'abord crer un nouvel lment, lui assigner sa valeur, et mettre
l'adresse de l'lment suivant NULL. En effet,, comme cet lment va terminer la liste nous devons signaler qu'il n'y a plus
d'lment suivant. Ensuite, il faut faire pointer le dernier lment de liste originale sur le nouvel lment que nous venons de
crer. Pour ce faire, il faut crer un pointeur temporaire sur element qui va se dplacer d'lment en lment, et regarder si cet
lment est le dernier de la liste. Un lment sera forcment le dernier de la liste si NULL est assign son champ nxt.

Code : C
llist ajouterEnFin(llist liste, int valeur)
{
/* On cre un nouvel lment */
element* nouvelElement = malloc(sizeof(element));
/* On assigne la valeur au nouvel lment */
nouvelElement->val = valeur;
/* On ajoute en fin, donc aucun lment ne va suivre */
nouvelElement->nxt = NULL;
if(liste == NULL)
{
/* Si la liste est vide il suffit de renvoyer l'lment
cr */
return nouvelElement;
}
else
{

www.openclassrooms.com

Les listes chanes

8/19

/* Sinon, on parcourt la liste l'aide d'un pointeur


temporaire et on
indique que le dernier lment de la liste est reli au nouvel
lment */
element* temp=liste;
while(temp->nxt != NULL)
{
temp = temp->nxt;
}
temp->nxt = nouvelElement;
return liste;
}
}

Comme vous pouvez le constater, nous nous dplaons le long de la liste chane grce au pointeur temp. Si l'lment point par
temp n'est pas le dernier (temp->nxt != NULL), on avance d'un cran (temp = temp->nxt) en assignant temp l'adresse de l'lment
suivant. Une fois que l'on est au dernier lment, il ne reste plus qu' le relier au nouvel lment.
Si vous pensez avoir bien saisi ces deux fonctions, je vous invite passer la partie suivante, dans laquelle je vais vous
proposer quelques exercices. Le premier sera fondamental puisqu'il nous permettra d'afficher le contenu d'une liste chane.

Exercices (1/2)
Exercice n1
Vous allez maintenant pouvoir vous tester. Votre mission, si vous l'acceptez, est de coder la fonction afficherListe. Vous devrez
parcourir la liste jusqu'au bout et afficher toutes les valeurs qu'elle contient. Voici son prototype :
Code : C
void afficherListe(llist liste);

Correction
Secret (cliquez pour afficher)
Code : C
void afficherListe(llist liste)
{
element *tmp = liste;
/* Tant que l'on n'est pas au bout de la liste */
while(tmp != NULL)
{
/* On affiche */
printf("%d ", tmp->val);
/* On avance d'une case */
tmp = tmp->nxt;
}
}

Alors ? Qu'est ce que a donne ? Si vous avez russi ce premier exercice, vous tes sur la bonne voie.
Quelques explications pour ceux qui ont eu quelques difficults : la seule chose faire est de se dplacer le long de la liste
chane grce au pointeur tmp. Si ce pointeur tmp pointe sur NULL, c'est que l'on a atteint le bout de la chane, sinon c'est
que nous sommes sur un lment dont il faut afficher la valeur.

Exercice n2
www.openclassrooms.com

Les listes chanes

9/19

Un deuxime exercice utilisant trois fonctions que nous avons vues jusqu' prsent :
ajouterEnTete
ajouterEnFin
afficherListe
Vous devez crire le main permettant de remplir et afficher la liste chane ci-dessous. Vous ne devrez utiliser qu'une seule boucle
for.
Code : Console
10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10

Aucune autre directive pour cet exercice qui ncessite peut-tre un peu de logique, mais question technique vous devriez tre au
point.

Correction
Secret (cliquez pour afficher)
Code : C
int main(int argc, char **argv)
{
llist ma_liste = NULL;
int i;
for(i=1;i<=10;i++)
{
ma_liste = ajouterEnTete(ma_liste, i);
ma_liste = ajouterEnFin(ma_liste, i);
}
afficherListe(ma_liste);
supprimerListe(ma_liste); // Libre les ressources, nous
verrons cette fonction plus tard.
}

return 0;

Une simple boucle suffit. Au dbut, la liste est vide. Vous ajoutez un premier lment gal 1, puis un deuxime 1. Aprs un
premier passage, votre liste contient deux lments 1. Au deuxime passage, nous allons ajouter un lment 2 en tte, puis un
lment 2 en fin pour obtenir 2 1 1 2. Il suffit alors de rpter l'opration dix fois.

Exercice n3
L'exercice suivant est le plus simple des trois, mais il me faut vous le montrer. crivez une fonction qui renvoie 1 si la liste est
vide, et 0 si elle contient au moins un lment. Son prototype est le suivant :
Code : C
int estVide(llist liste);

Vous vous demandez srement l'intrt d'crire une telle fonction... eh bien quand vous codez une bibliothque, le mieux est de
"masquer" le fonctionnement interne de vos codes. L'utilisateur n'est pas cens savoir qu'une liste vide sera gale NULL, ni
mme que le type llist est un pointeur. Lui, il dclare une llist sans savoir comment elle est cre, puis l'utilise (ajoute ou supprime

www.openclassrooms.com

Les listes chanes

10/19

des lments, trie sa liste, etc...) grce aux fonctions de la bibliothque. Dans certains cas, il lui faudra tester si la liste est vide, il
utilisera par exemple :
Code : C
if(estVide(ma_liste))
{
printf("La liste est vide");
}
else
{
afficherListe(ma_liste);
}

A vous donc pour cette fonction !

Correction
Secret (cliquez pour afficher)
Code : C
int estVide(lliste liste)
{
if(liste == NULL)
{
return 1;
}
else
{
return 0;
}
}

Ou bien, en condens :
Code : C
int estVide(llist liste)
{
return (liste == NULL)? 1 : 0;
}

Alors ? Rien de plus simple, non ?


Si la liste est NULL, il ne contient aucun lment, elle est donc vide. Sinon, c'est qu'elle contient au minimum un lment.

Nous voil au bout de cette premire srie d'exercices. Dans la section suivante, nous allons voir plein de fonctions plus
complexes permettant de manipuler nos listes chanes !

Manipuler les listes chaines (2/2)


Cette fois, a va monter d'un cran niveau difficult. Nous allons voir tout un tas de fonctions, pour supprimer des lments,
rechercher un lment... Je vous conseille si vous n'avez pas tout compris de revenir un peu en arrire, de faire des essais avec
votre compilateur prfr, parce que tout ce que nous allons voir fonctionne toujours sur le mme principe. Je considrerais ce
que j'ai prcdemment montr comme acquis. Cette partie va se drouler comme ceci : j'explique l'algorithme gnral de la fonction
puis je donne son code comment.

www.openclassrooms.com

Les listes chanes

11/19

Prts ? On y va !

Supprimer un lment en tte


Il s'agit l de supprimer le premier lment de la liste. Pour ce faire, il nous faudra utiliser la fonction free que vous connaissez
certainement. Si la liste n'est pas vide, on stocke l'adresse du premier lment de la liste aprs suppression (i.e. l'adresse du 2me
lment de la liste originale), on supprime le premier lment, et on renvoie la nouvelle liste. Attention quand mme ne pas
librer le premier lment avant d'avoir stock l'adresse du second, sans quoi il sera impossible de la rcuprer.
Code : C
llist supprimerElementEnTete(llist liste)
{
if(liste != NULL)
{
/* Si la liste est non vide, on se prpare renvoyer
l'adresse de
l'lment en 2me position */
element* aRenvoyer = liste->nxt;
/* On libre le premier lment */
free(liste);
/* On retourne le nouveau dbut de la liste */
return aRenvoyer;
}
else
{
return NULL;
}
}

Supprimer un lment en fin de liste


Cette fois-ci, il va falloir parcourir la liste jusqu' son dernier lment, indiquer que l'avant-dernier lment va devenir le dernier de
la liste et librer le dernier lment pour enfin retourner le pointeur sur le premier lment de la liste d'origine.
Code : C
llist supprimerElementEnFin(llist liste)
{
/* Si la liste est vide, on retourne NULL */
if(liste == NULL)
return NULL;
/* Si la liste contient un seul lment */
if(liste->nxt == NULL)
{
/* On le libre et on retourne NULL (la liste est
maintenant vide) */
free(liste);
return NULL;
}
/* Si la liste contient au moins deux lments */
element* tmp = liste;
element* ptmp = liste;
/* Tant qu'on n'est pas au dernier lment */
while(tmp->nxt != NULL)
{
/* ptmp stock l'adresse de tmp */
ptmp = tmp;

www.openclassrooms.com

Les listes chanes


*/

12/19
/* On dplace tmp (mais ptmp garde l'ancienne valeur de tmp

tmp = tmp->nxt;
}
/* A la sortie de la boucle, tmp pointe sur le dernier lment,
et ptmp sur
l'avant-dernier. On indique que l'avant-dernier devient la fin de
la liste
et on supprime le dernier lment */
ptmp->nxt = NULL;
free(tmp);
return liste;
}

Rechercher un lment dans une liste


Le but du jeu cette fois est de renvoyer l'adresse du premier lment trouv ayant une certaine valeur. Si aucun lment n'est
trouv, on renverra NULL. L'intrt est de pouvoir, une fois le premier lment trouv, chercher la prochaine occurrence en
recherchant partir de elementTrouve->nxt. On parcourt donc la liste jusqu'au bout, et ds qu'on trouve un lment qui
correspond ce que l'on recherche, on renvoie son adresse.
Code : C
llist rechercherElement(llist liste, int valeur)
{
element *tmp=liste;
/* Tant que l'on n'est pas au bout de la liste */
while(tmp != NULL)
{
if(tmp->val == valeur)
{
/* Si l'lment a la valeur recherche, on renvoie son
adresse */
return tmp;
}
tmp = tmp->nxt;
}
return NULL;
}

Compter le nombre d'occurrences d'une valeur


Pour ce faire, nous allons utiliser la fonction prcdente permettant de rechercher un lment. On cherche une premire
occurrence : si on la trouve, alors on continue la recherche partir de l'lment suivant, et ce tant qu'il reste des occurrences de
la valeur recherche. Il est aussi possible d'crire cette fonction sans utiliser la prcdente bien entendu, en parcourant
l'ensemble de la liste avec un compteur que l'on incrmente chaque fois que l'on passe sur un lment ayant la valeur
recherche. Cette fonction n'est pas beaucoup plus complique, mais il est intressant d'un point de vue algorithmique de
rutiliser des fonctions pour simplifier nos codes.
Code : C
int nombreOccurences(llist liste, int valeur)
{
int i = 0;
/* Si la liste est vide, on renvoie 0 */
if(liste == NULL)

www.openclassrooms.com

Les listes chanes

13/19
return 0;

/* Sinon, tant qu'il y a encore un lment ayant la val =


valeur */
while((liste = rechercherElement(liste, valeur)) != NULL)
{
/* On incrmente */
liste = liste->nxt;
i++;
}
/* Et on retourne le nombre d'occurrences */
return i;
}

Recherche du i-me lment


Pour le coup, c'est une fonction relativement simple. Il suffit de se dplacer i fois l'aide du pointeur tmp le long de la liste
chane et de renvoyer l'lment l'indice i. Si la liste contient moins de i lment(s), alors nous renverrons NULL.
Code : C
llist element_i(llist liste, int indice)
{
int i;
/* On se dplace de i cases, tant que c'est possible */
for(i=0; i<indice && liste != NULL; i++)
{
liste = liste->nxt;
}
/* Si l'lment est NULL, c'est que la liste contient moins de
i lments */
if(liste == NULL)
{
return NULL;
}
else
{
/* Sinon on renvoie l'adresse de l'lment i */
return liste;
}
}

Rcuprer la valeur d'un lment


C'est une fonction du mme style que la fonction estVide. Elle sert "masquer" le fonctionnement interne l'utilisateur. Il suffit
simplement de renvoyer l'utilisateur la valeur d'un lment. Il faudra renvoyer un code d'erreur entier si l'lment n'existe pas (la
liste est vide), c'est donc vous de dfinir une macro selon l'utilisation que vous voulez faire des listes chanes. Dans ce code,
je considre qu'on ne travaille qu'avec des nombres entiers positifs, on renverra donc -1 pour une erreur. Vous pouvez mettre ici
n'importe quelle valeur que vous tes srs de ne pas utiliser dans votre liste. Une autre solution consiste renvoyer un pointeur
sur int au lieu d'un int, vous laissant donc la possibilit de renvoyer NULL.
Code : C
#define ERREUR -1
int valeur(llist liste)
{

www.openclassrooms.com

Les listes chanes


}

14/19

return ((liste == NULL)?ERREUR:(liste->val));

Compter le nombre d'lments d'une liste chan


C'est un algorithme vraiment simple. Vous parcourez la liste de bout en bout et incrmentez d'un pour chaque nouvel lment que
vous trouvez. Cet algorithme n'ayant aucun intrt au point o nous en sommes, je vais en profiter pour vous faire dcouvrir un
nouveau type d'algorithme. Jusqu' maintenant, nous n'avons utilis que des algorithmes itratifs qui consistent boucler tant
que l'on n'est pas au bout. Nous allons voir qu'il existe des algorithmes que l'on appellent rcursifs et qui consistent en fait
demander une fonction de s'appeler elle-mme. Attention : il faudrait un big-tuto complet pour tout expliquer propos des
algorithmes rcursifs, ce n'est vraiment que pour vous montrer que ce genre de choses existe que je vais les utiliser dans les deux
prochains codes.
Avant tout, je pense qu'un petit point d'explication s'impose.
Pour crer un algorithme rcursif, il faut connatre la condition d'arrt (ou condition de sortie) et la condition de rcurrence. Il faut
en fait vous imaginer que votre fonction a fait son office pour les n-1 lments suivants, et qu'il ne reste plus qu' traiter le
dernier lment. Lisez le code suivant. N'ayez pas peur si ceci vous semble obscur, ce n'est pas essentiel pour utiliser les listes
chanes. Maintenant, je suis sr que vous tes au point et vous pouvez donc de manire itrative crer peu prs tout ce qui
peut se faire.
Code : C
int nombreElements(llist liste)
{
/* Si la liste est vide, il y a 0 lment */
if(liste == NULL)
return 0;
/* Sinon, il y a un lment (celui que l'on est en train de
traiter)
plus le nombre d'lments contenus dans le reste de la liste */
return nombreElements(liste->nxt)+1;
}

Effacer tous les lments ayant une certaine valeur


Pour cette dernire fonction, nous allons encore une fois utiliser un algorithme rcursif. Mme si la rcursivit vous semble tre
une notion complexe (et a l'est srement), elle simplifie grandement les algorithmes dans certains cas, et dans celui-ci tout
particulirement. Je vous donne le code titre indicatif, vous pourrez vous mme recoder cette fonction avec un algorithme
itratif si vous le voulez.
Code : C
llist supprimerElement(llist liste, int valeur)
{
/* Liste vide, il n'y a plus rien supprimer */
if(liste == NULL)
return NULL;
/* Si l'lment en cours de traitement doit tre supprim */
if(liste->val == valeur)
{
/* On le supprime en prenant soin de mmoriser
l'adresse de l'lment suivant */
element* tmp = liste->nxt;
free(liste);

www.openclassrooms.com

Les listes chanes

15/19

/* L'lment ayant t supprim, la liste commencera


l'lment suivant
pointant sur une liste qui ne contient plus aucun lment ayant la
valeur recherche */
tmp = supprimerElement(tmp, valeur);
return tmp;
}
else
{
/* Si l'lement en cours de traitement ne doit pas tre
supprim,
alors la liste finale commencera par cet lment et suivra une
liste ne contenant
plus d'lment ayant la valeur recherche */
liste->nxt = supprimerElement(liste->nxt, valeur);
return liste;
}
}

Exercices (2/2)
Exercice n1
Voil... Maintenant, vous tes des as en matire de liste chanes, j'en suis sr. Je vous propose donc quelques exercices. Le
premier sera de coder de manire itrative la fonction nombreElements dont je vous rappelle le prototype :
Code : C
int nombreElements(llist liste);

C'est un exercice qui ne devrait pas vous poser de problmes : bonne chance.
Secret (cliquez pour afficher)
Code : C
int nombreElements(llist liste)
{
int nb = 0;
element* tmp = liste;

/* On parcours la liste */
while(tmp != NULL)
{
/* On incrmente */
nb++;
tmp = tmp->nxt;
}
/* On retourne le nombre d'lments parcourus */
return nb;

C'est aussi simple que a. On parcourt simplement la liste tant que l'on n'est pas arriv au bout, et on incrmente le compteur
nb que l'on renvoie pour finir.

Exercice n2
Nous allons maintenant crire une fonction permettant d'effacer compltement une liste chane de la mmoire. Je vous propose

www.openclassrooms.com

Les listes chanes

16/19

d'crire avec un algorithme itratif dans un premier temps, puis une seconde fois grce un algorithme rcursif. Dans le premier
cas, vous devez parcourir la liste, stocker l'lment suivant, effacer l'lment courant et avancer d'une case. A la fin la liste est
vide, nous retournerons NULL.
Secret (cliquez pour afficher)
Code : C
llist effacerListe(llist liste)
{
element* tmp = liste;
element* tmpnxt;
/* Tant que l'on n'est pas au bout
while(tmp != NULL)
{
/* On stocke l'lment suivant
avancer */
tmpnxt = tmp->nxt;
/* On efface l'lment courant
free(tmp);
/* On avance d'une case */
tmp = tmpnxt;
}
/* La liste est vide : on retourne
return NULL;
}

de la liste */
pour pouvoir ensuite
*/

NULL */

Code : C
llist effacerListe(llist liste)
{
if(liste == NULL)
{
/* Si la liste est vide, il n'y a rien effacer, on
retourne
une liste vide i.e. NULL */
return NULL;
}
else
{
/* Sinon, on efface le premier lment et on retourne le
reste de la
liste efface */
element *tmp;
tmp = liste->nxt;
free(liste);
return effacerListe(tmp);
}
}

Et voil : vous en savez maintenant un peu plus sur ce que sont les listes chanes. Vous pourrez amliorer ceci en utilisant les
listes doublement chanes, qui sont en fait une liste d'lments qui pointent la fois sur l'lment suivant, mais aussi sur
l'lment prcdent, ce qui vous permet de revenir en arrire plus facilement qu'avec les listes simplement chanes. Vous pouvez
complter votre bibliothque avec des fonctions de tri, de recherche de minimum, de maximum et bien d'autre choses...
Passons maintenant un petit QCM, afin de vrifier que vous avez tout saisi !

Q.C.M.
Le premier QCM de ce cours vous est offert en libre accs.
Pour accder aux suivants

www.openclassrooms.com

Les listes chanes

17/19

Connectez-vous Inscrivez-vous
Une erreur s'est glisse dans le code suivant :
Code : C
typedef struct element element;
struct element
{
int val;
struct element nxt;
};

Il manque un typedef
Il manque une toile
Le code est juste

J'excute le programme contenant le main suivant, que va-t-il se passer ?


Code : C
int main(int argc, char **argv)
{
element* ma_liste;
ma_liste = ajouterEnTete(ma_liste, 12);
afficherListe(ma_liste);
return 0;
}

Rien du tout
a ne compile pas : tu as mis element* la place de llist pour dclarer ma_liste
Une erreur de segmentation

Correction !
Statistiques de rponses au Q CM

Eh bien il semblerait que vous tes au point. Comme vous avez pu le constater, le choix d'utiliser ou non les listes chanes est
fait lors de l'implmentation de votre algorithme dans un langage. Vous devrez toujours faire des compromis.
J'avais parl d'introduire les listes doublement chanes, ce que je vais faire maintenant pour vous permettre d'aller plus loin.
L'ide est la suivante : un lment ne va plus se composer d'une valeur et d'une adresse, mais d'une valeur et de deux adresses :
l'adresse de l'lment suivant mais aussi l'adresse de l'lment prcdent. On pourra tirer avantage de cette spcificit pour lire
des listes l'envers. Avoir l'adresse de l'lment prcdent peut simplifier les algorithmes de vos fonctions, mais tout aussi bien
les compliquer car c'est maintenant deux pointeurs qu'il faut grer lors d'un ajout ou d'une suppression.
Nous sommes loin d'avoir cod une bibliothque complte, mais vos connaissances vous permettent maintenant de continuer
seuls et d'implmenter toutes sortes de fonctions.
Merci d'avoir lu ce tutoriel jusqu'au bout. Si une ou plusieurs erreurs s'y sont glisses (ce n'est pas exclu), prvenez-moi par MP.
Remerciements Nicolas et Mleg pour avoir vrifi, test ce tutoriel et permis de ce fait sa parution.

Je sais que le sujet des listes chaines est souvent abord lors de l'entre dans les tudes suprieures, aussi je
serais ravis d'apprendre qu'un professeur vous a redirig sur mon tutoriel, si tel est le cas n'hsitez pas me le faire
savoir par message !

A bientt !

www.openclassrooms.com

Les listes chanes

18/19

Partager

www.openclassrooms.com