Académique Documents
Professionnel Documents
Culture Documents
Cours
Parcours
Forums
Partenaires
�tudes
Premium
modou sarry
Fran�ais
Fil d'Ariane
Accueil
Cours
Les listes cha�n�es
Publicit�
Les listes cha�n�es
Mis � jour le mercredi 30 octobre 2013
Licence
Introduction du cours
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 entra�nement, en ce qui concerne les pointeurs, entre autres, mais fera
appel � toutes vos connaissances du langage C.
Le but de ce tutoriel est de vous initier aux listes cha�n�es, une autre fa�on
d'impl�menter un conteneur, la plus courante �tant les tableaux. A la fin de ce
cours, vous serez capables de coder votre propre biblioth�que permettant la
cr�ation et la manipulation de listes simplement cha�n�es. Les listes doublement
chain�es seront introduites pour terminer afin que vous puissiez am�liorer votre
biblioth�que.
Je suis s�r que vous �tes pr�ts : nous allons donc commencer !
G�n�ralit�s sur les listes chain�es
Nous allons essayer de voir ceci plus en d�tail sur ces sch�mas :
Image utilisateur
Vous avez sur ce sch�ma la repr�sentation que l'on pourrait faire d'un tableau et
d'une liste cha�n�e. Chacune de ces repr�sentations poss�de ses avantages et
inconv�nients. C'est lors de l'�criture de votre programme que vous devez vous
poser la question de savoir laquelle des deux m�thodes est la plus int�ressante.
Dans une liste cha�n�e, la taille est inconnue au d�part, la liste peut avoir
autant d'�l�ments que votre m�moire le permet.
Il est en revanche impossible d'acc�der directement � l'�l�ment i de la liste
chain�e.
Pour ce faire, il vous faudra traverser les i-1 �l�ments pr�c�dents de la
liste.
Pour d�clarer une liste cha�n�e, il suffit de cr�er le pointeur qui va pointer
sur le premier �l�ment de votre liste cha�n�e, aucune taille n'est donc �
sp�cifier.
Voil� deux sch�mas pour expliquer comment se passent l'ajout et la suppression d'un
�l�ment d'une liste cha�n�e. Remarquez le symbole en bout de cha�ne qui signifie
que l'adresse de l'�l�ment suivant ne pointe sur rien, c'est-�-dire sur NULL.
Image utilisateur
Comme vous vous en doutez certainement maintenant, la liste cha�n�e est un type
structur�. Nous en avons termin� avec ces quelques g�n�ralit�s, nous allons pouvoir
passer � la d�finition d'une structure de donn�es nous permettant de cr�er cette
fameuse liste !
Vous vous demandez s�rement de quel type sera l'�l�ment de la liste cha�n�e. A ceci
je ne peux r�pondre que... � vous de voir. En effet, vous pouvez cr�er des listes
cha�n�es de n'importe quel type d'�l�ments : entiers, caract�res, structures,
tableaux, voir m�me d'autres listes cha�n�es... Il vous est m�me possible de
combiner plusieurs types dans une m�me liste.
Allez : vous avez assez patient�, voici la d�claration d'une liste simplement
cha�n�e d'entiers :
#include <stdlib.h>
typedef struct element element;
struct element
{
int val;
struct element *nxt;
};
typedef element* llist;
On cr�e le type element qui est une structure contenant un entier (val) et un
pointeur sur �l�ment (nxt), qui contiendra l'adresse de l'�l�ment suivant. Ensuite,
il nous faut cr�er le type llist (pour linked list = liste cha�n�e) qui est en fait
un pointeur sur le type element. Lorsque nous allons d�clarer la liste cha�n�e,
nous devrons d�clarer un pointeur sur element, l'initialiser � NULL, pour pouvoir
ensuite allouer le premier �l�ment. N'oubliez pas d'inclure stdlib.h afin de
pouvoir utiliser la macro NULL. Comme vous allez le constater, nous avons juste
cr�e le type llist afin de simplifier la d�claration.
#include <stdlib.h>
typedef struct element element;
struct element
{
int val;
struct element *nxt;
};
typedef element* llist;
int main(int argc, char **argv)
{
/* D�clarons 3 listes cha�n�es de fa�ons diff�rentes mais �quivalentes */
llist ma_liste1 = NULL;
element *ma_liste2 = NULL;
struct element *ma_liste3 = NULL;
return 0;
}
Maintenant que nous savons comment d�clarer une liste cha�n�e, il serait
int�ressant d'apprendre � ajouter des �l�ments dans cette liste, ainsi que de lire
ce qu'elle contient. C'est ce que nous allons �tudier dans cette premi�re partie
sur la manipulation des listes cha�n�es. Je vous invite � essayer par vous-m�mes 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 �l�ment de la liste.
Ajouter un �l�ment
Lorsque nous voulons ajouter un �l�ment dans une liste cha�n�e, il faut savoir o�
l'ins�rer. Les deux ajouts g�n�riques des listes cha�n�es sont les ajouts en t�te,
et les ajouts en fin de liste. Nous allons �tudier ces deux moyens d'ajouter un
�l�ment � une liste.
Ajouter en t�te
Lors d'un ajout en t�te, nous allons cr�er un �l�ment, lui assigner la valeur que
l'on veut ajouter, puis pour terminer, raccorder cet �l�ment � la liste pass�e en
param�tre. Lors d'un ajout en t�te, on devra donc assigner � nxt l'adresse du
premier �l�ment de la liste pass� en param�tre. Visualisons tout ceci sur un sch�ma
:
Image utilisateur
C'est l'ajout le plus simple des deux. Il suffit de cr�er un nouvel �l�ment puis de
le relier au d�but 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 �l�ment.
Ajouter en fin de liste
Cette fois-ci, c'est un peu plus compliqu�. Il nous faut tout d'abord cr�er un
nouvel �l�ment, lui assigner sa valeur, et mettre l'adresse de l'�l�ment suivant �
NULL. En effet,, comme cet �l�ment va terminer la liste nous devons signaler qu'il
n'y a plus d'�l�ment suivant. Ensuite, il faut faire pointer le dernier �l�ment de
liste originale sur le nouvel �l�ment que nous venons de cr�er. Pour ce faire, il
faut cr�er un pointeur temporaire sur element qui va se d�placer d'�l�ment en
�l�ment, et regarder si cet �l�ment est le dernier de la liste. Un �l�ment sera
forc�ment le dernier de la liste si NULL est assign� � son champ nxt.
Image utilisateur
Comme vous pouvez le constater, nous nous d�pla�ons le long de la liste cha�n�e
gr�ce au pointeur temp. Si l'�l�ment 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'�l�ment suivant. Une fois que l'on est au dernier �l�ment, il ne reste plus
qu'� le relier au nouvel �l�ment.
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
cha�n�e.
Exercices (1/2)
Exercice n�1
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 :
Correction
Alors ? Qu'est ce que �a donne ? Si vous avez r�ussi ce premier exercice, vous �tes
sur la bonne voie.
Quelques explications pour ceux qui ont eu quelques difficult�s : la seule chose �
faire est de se d�placer le long de la liste cha�n�e gr�ce au pointeur tmp. Si ce
pointeur tmp pointe sur NULL, c'est que l'on a atteint le bout de la cha�ne, sinon
c'est que nous sommes sur un �l�ment dont il faut afficher la valeur.
Exercice n�2
Un deuxi�me exercice utilisant trois fonctions que nous avons vues jusqu'�
pr�sent :
ajouterEnTete
ajouterEnFin
afficherListe
Vous devez �crire le main permettant de remplir et afficher la liste cha�n�e ci-
dessous. Vous ne devrez utiliser qu'une seule boucle for.
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 n�cessite peut-�tre un peu de logique,
mais question technique vous devriez �tre au point.
Correction
Une simple boucle suffit. Au d�but, la liste est vide. Vous ajoutez un premier
�l�ment �gal � 1, puis un deuxi�me 1. Apr�s un premier passage, votre liste
contient deux �l�ments 1. Au deuxi�me passage, nous allons ajouter un �l�ment 2 en
t�te, puis un �l�ment 2 en fin pour obtenir 2 1 1 2. Il suffit alors de r�p�ter
l'op�ration dix fois.
Exercice n�3
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 �l�ment. Son prototype est le suivant :
Vous vous demandez s�rement l'int�r�t d'�crire une telle fonction... eh bien quand
vous codez une biblioth�que, 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 m�me que le type llist est un pointeur. Lui, il d�clare une llist sans
savoir comment elle est cr��e, puis l'utilise (ajoute ou supprime des �l�ments,
trie sa liste, etc...) gr�ce aux fonctions de la biblioth�que. Dans certains cas,
il lui faudra tester si la liste est vide, il utilisera par exemple :
if(estVide(ma_liste))
{
printf("La liste est vide");
}
else
{
afficherListe(ma_liste);
}
Correction
Ou bien, en condens� :
Nous voil� au bout de cette premi�re s�rie d'exercices. Dans la section suivante,
nous allons voir plein de fonctions plus complexes permettant de manipuler nos
listes cha�n�es !
Manipuler les listes chain�es (2/2)
Cette fois, �a va monter d'un cran niveau difficult�. Nous allons voir tout un tas
de fonctions, pour supprimer des �l�ments, rechercher un �l�ment... Je vous
conseille si vous n'avez pas tout compris de revenir un peu en arri�re, de faire
des essais avec votre compilateur pr�f�r�, parce que tout ce que nous allons voir
fonctionne toujours sur le m�me principe. Je consid�rerais ce que j'ai pr�c�demment
montr� comme acquis. Cette partie va se d�rouler comme ceci : j'explique
l'algorithme g�n�ral de la fonction puis je donne son code comment�.
Pr�ts ? On y va !
Supprimer un �l�ment en t�te
Le but du jeu cette fois est de renvoyer l'adresse du premier �l�ment trouv� ayant
une certaine valeur. Si aucun �l�ment n'est trouv�, on renverra NULL. L'int�r�t est
de pouvoir, une fois le premier �l�ment trouv�, chercher la prochaine occurrence en
recherchant � partir de elementTrouve->nxt. On parcourt donc la liste jusqu'au
bout, et d�s qu'on trouve un �l�ment qui correspond � ce que l'on recherche, on
renvoie son adresse.
C'est une fonction du m�me style que la fonction estVide. Elle sert � "masquer" le
fonctionnement interne � l'utilisateur. Il suffit simplement de renvoyer �
l'utilisateur la valeur d'un �l�ment. Il faudra renvoyer un code d'erreur entier si
l'�l�ment n'existe pas (la liste est vide), c'est donc � vous de d�finir une macro
selon l'utilisation que vous voulez faire des listes cha�n�es. Dans ce code, je
consid�re 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
s�rs 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.
#define ERREUR -1
int valeur(llist liste)
{
return ((liste == NULL)?ERREUR:(liste->val));
}
Pour cette derni�re fonction, nous allons encore une fois utiliser un algorithme
r�cursif. M�me si la r�cursivit� vous semble �tre une notion complexe (et �a l'est
s�rement), elle simplifie grandement les algorithmes dans certains cas, et dans
celui-ci tout particuli�rement. Je vous donne le code � titre indicatif, vous
pourrez vous m�me recoder cette fonction avec un algorithme it�ratif si vous le
voulez.
Exercices (2/2)
Exercice n�1
Voil�... Maintenant, vous �tes des as en mati�re de liste cha�n�es, j'en suis s�r.
Je vous propose donc quelques exercices. Le premier sera de coder de mani�re
it�rative la fonction nombreElements dont je vous rappelle le prototype :
int nombreElements(llist liste);
C'est un exercice qui ne devrait pas vous poser de probl�mes : bonne chance.
C'est aussi simple que �a. On parcourt simplement la liste tant que l'on n'est pas
arriv� au bout, et on incr�mente le compteur nb que l'on renvoie pour finir.
Exercice n�2
Nous allons maintenant �crire une fonction permettant d'effacer compl�tement une
liste cha�n�e de la m�moire. Je vous propose d'�crire avec un algorithme it�ratif
dans un premier temps, puis une seconde fois gr�ce � un algorithme r�cursif. Dans
le premier cas, vous devez parcourir la liste, stocker l'�l�ment suivant, effacer
l'�l�ment courant et avancer d'une case. A la fin la liste est vide, nous
retournerons NULL.
Et voil� : vous en savez maintenant un peu plus sur ce que sont les listes
cha�n�es. Vous pourrez am�liorer ceci en utilisant les listes doublement cha�n�es,
qui sont en fait une liste d'�l�ments qui pointent � la fois sur l'�l�ment suivant,
mais aussi sur l'�l�ment pr�c�dent, ce qui vous permet de revenir en arri�re plus
facilement qu'avec les listes simplement cha�n�es. Vous pouvez compl�ter votre
biblioth�que avec des fonctions de tri, de recherche de minimum, de maximum et bien
d'autre choses...
Passons maintenant � un petit QCM, afin de v�rifier que vous avez tout saisi !
Eh bien il semblerait que vous �tes au point. Comme vous avez pu le constater, le
choix d'utiliser ou non les listes cha�n�es est fait lors de l'impl�mentation de
votre algorithme dans un langage. Vous devrez toujours faire des compromis.
J'avais parl� d'introduire les listes doublement cha�n�es, ce que je vais faire
maintenant pour vous permettre d'aller plus loin. L'id�e est la suivante : un
�l�ment ne va plus se composer d'une valeur et d'une adresse, mais d'une valeur et
de deux adresses : l'adresse de l'�l�ment suivant mais aussi l'adresse de l'�l�ment
pr�c�dent. On pourra tirer avantage de cette sp�cificit� pour lire des listes �
l'envers. Avoir l'adresse de l'�l�ment pr�c�dent peut simplifier les algorithmes de
vos fonctions, mais tout aussi bien les compliquer car c'est maintenant deux
pointeurs qu'il faut g�rer lors d'un ajout ou d'une suppression.
Nous sommes loin d'avoir cod� une biblioth�que compl�te, mais vos connaissances
vous permettent maintenant de continuer seuls et d'impl�menter toutes sortes de
fonctions.
Merci d'avoir lu ce tutoriel jusqu'au bout. Si une ou plusieurs erreurs s'y sont
gliss�es (ce n'est pas exclu), pr�venez-moi par MP.
Je sais que le sujet des listes chain�es est souvent abord� lors de l'entr�e dans
les �tudes sup�rieures, aussi je serais ravis d'apprendre qu'un professeur vous a
redirig� sur mon tutoriel, si tel est le cas n'h�sitez pas � me le faire savoir par
message !
A bient�t !
L'auteur
lexou
D�couvrez aussi ce cours en...
PDF
OpenClassrooms
Qui sommes-nous ?
Fonctionnement de nos cours
Recrutement
Nous contacter
Professionnels
Affiliation
Entreprises
Universit�s et �coles
Participez
Cr�er un cours
CourseLab
Aider � traduire
Conditions G�n�rales d'Utilisation
Suivez-nous
Le blog OpenClassrooms
Pas du tout
Oui, tout � fait
Powered by SatisMeter