Chapitre III
Structure de donn´ ees Les listes chaˆın´ ees
Fili` ere SMIA Parcours SMI Semestre4
Algorithmique avanc´eeCes informations sontorganis´eesdans lam´emoire principaleet dans lesm´emoires auxiliaires.
Par ailleurs, notons que l’ordinateurd´efinitauniveau mat´eriel:
Unjeu d’instructions ´el´ementaires(additionner, soustraire, multiplier...), Quelquesrepr´esentations de donn´ees ´el´ementaires(bits).
Mais, il faut signaler que le mat´erielne supporteque desdonn´ees ´el´ementaires, doncnon structur´ees.
On peut ainsi d´efinir unedonn´ee structur´eecomme ´etant unecollectionorganis´ee de donn´ees ´el´ementaires.
En informatique, on appelle une telle collection, unestructure de donn´ees.
Unestructure de donn´eesest donc unemani`ere d’organiseret derepr´esenterdes informations en m´emoire centrale et dans les m´emoires auxiliaires.
Une structure de donn´eescontient deux types de renseignement: les informations `astocker,
lesliensentre ces informations.
On peut distinguerdeux typesde liens :
Liens implicites :l’adressede l’information estcalcul´eeen fonction del’emplacement physiquede l’information en m´emoire.
1. Introduction : Objectif et Motivation
En langage C, il existe ungrand nombrede structure de donn´ees :
Exemple :lestableauxlesstructures, leslistes chaˆın´ees, lespiles, lesfiles, lesarbres binaires...
Le choixd’une structured´epend, en g´en´eral, desop´erations`a r´ealiser sur les informations.Certaines structuressontplus adapt´esque d’autres `acertaines op´erations.
L’objectif est lagestion d’un ensemble fini d’´el´ementsdont le nombre n’est pas fix´e.
Les ´el´ements de cet ensemble peuvent ˆetre dediff´erentes types: nombresentiersouflottants,chaˆınes de caract`eres,...
On ne s’int´eressera pas aux ´el´ementsde l’ensemble en question mais auxop´erationsque l’on effectue sur cet ensemble,ind´ependamment de la naturede ses ´el´ements.
En programmation informatique, ces ensembles sont consid´er´es comme desobjets dynamiques.
En effet, le nombre de leurs ´el´ementsvarie au cours de l’ex´ecutiondu programme, puisqu’on peut yajouter etsupprimerdes ´el´ements en cours de traitement.
Plus pr´ecis´ement lesop´erationsque l’ons’autorisesur les ensembles sont les suivantes : testersi un ensemble est vide.
ajouterun ´el´ement `a un ensemble.
supprimerun ´el´ement `a un ensemble.
rechercherun ´el´ement dans un ensemble.
Cette gestion des ensembles doit, pour ˆetreefficace, r´epondre `adeux crit`eres: unminimum de place m´emoireutilis´ee,
et unminimum d’instructions ´el´ementairespour r´ealiser une op´eration.
Notons que la structure de donn´ ees la plus utilis´ ee pour manipuler des donn´ ees sont les tableaux.
Mais, dans certains cas, les tableaux ne constituent pas la meilleure solution pour stocker et manipuler les donn´ ees.
En effet, Si on veut supprimer un ´ el´ ement au milieu d’un tableau, il faut recopier les ´ el´ ements temporairement, r´ eallouer le tableau, puis le remplir ` a partir de l’´ el´ ement supprim´ e.
Ces manipulations sont coˆ uteuses en ressources.
En langage C, les listes chaˆın´ ees (ou tout simplement les listes) peuvent ˆ etre consid´ er´ ees comme des structures de donn´ ees tr` es pratiques pour manipuler des
´
el´ ements d’un ensemble d’objets dynamiques.
En effet, une liste chaˆın´ ee est diff´ erente par rapport ` a un tableau dans le sens o` u ses ´ el´ ements sont r´ epartis dans la m´ emoire et reli´ es entre eux par des pointeurs.
Ceci permet d’ajouter et de supprimer des ´ el´ ements d’une liste ` a n’importe quel
endroit, sans modifier la liste enti` ere.
2. Les listes chaˆın´ ees
Une liste chaˆın´ ee est une structure de base de la programmation informatique.
C’est une structure de donn´ ees dans laquelle les objets sont stock´ es de mani` ere ordonn´ ee (l’ordre signifie que chaque objet poss` ede une position dans la liste).
Cependant, contrairement au tableau, pour lequel l’ordre est d´ etermin´ e par les indices, l’ordre d’une liste chaˆın´ ee est d´ etermin´ e par un pointeur dans chaque objet.
Les listes chaˆın´ ees sont des structures dynamiques capables, d’accueillir un nombre infini d’´ el´ ements,
et de supporter toutes les op´ erations sur les ensembles dynamiques (insertion, suppression, recherche,...).
Dans la suite du chapitre, on utilise la liste chaˆın´ ee pour repr´ esenter un ensemble d’´ el´ ements.
Chaque ´ el´ ement est contenu dans une cellule (appel´ ee aussi maillon), et chaque cellule est compos´ ee d’une partie contenant l’information et d’au moins un pointeur.
Information
Pointeur vers le prochain élément
Information
Pointeur vers le prochain élément
Repr´esentation d’une cellule avec un seul pointeur.
Une liste chaˆın´ ee est donc une succession de cellules, dont le dernier porte une adresse de fin (le pointeur NULL). La premi` ere cellule de la liste est appel´ ee tˆ ete et la derni` ere cellule est appel´ ee queue.
L’acc` es ` a la liste chaˆın´ ee se fait par un pointeur vers le premier ´ el´ ement.
Pour atteindre un des ´ el´ ements de la liste,
on est oblig´ e de parcourir la liste depuis le d´ ebut.
A partir d’un ´ el´ ement quelconque,
on ne peut atteindre que le suivant.
Une liste chaˆın´ ee peut prendre diff´ erentes formes :
Elle peut ˆ etre simple (dite aussi simplement chaˆın´ ee) : chaque cellule est compos´ e de l’information et d’un seul pointeur (pointe sur l’adresse de la cellule suivante).
Ou doublement chaˆın´ ee : chaque cellule est compos´ e de l’information et de deux pointeurs (l’un pointe sur l’adresse de la cellule suivante et l’autre sur celle de la cellule pr´ ec´ edente).
Ou circulaire : la tˆ ete pointe sur la queue de la liste, et la queue pointe
2. Les listes chaˆın´ ees : 2.1 Les listes simplement chaˆın´ ees
Rappelons qu’une liste simplement chaˆın´ ee est une liste o` u chaque cellules contient des informations accessibles et modifiables par l’utilisateur ainsi qu’un pointeur vers la cellule suivante.
Valeur 3
Valeur 2 Valeur 4
Tête Valeur 1 NULL
Queue Valeur 3
Valeur 2 Valeur 4
Tête Valeur 1 NULL
Queue
Comme les listes simplement chaˆın´ ees sont une structure de donn´ ees importante en programmation informatique,
il est fondamental de s’int´ eresser ` a la mani` ere de les implanter en vue de leurs manipulations informatique.
Deux modes d’implantation peuvent ˆ etre envisag´ es : Implantation par pointeur.
Implantation par tableau.
D´ eclaration
Le langage Cpermet der´ealiser des listes chaˆın´ees`a l’aide desstructures.
En effet, lescellulessont desobjetsconstitu´es : d’un champ de donn´ees,
d’un pointeur vers la cellule suivante.
Lad´eclaration correspondanteest la suivante, o`u l’on suppose ici que lesvaleurs stock´eesdans chaque cellule sont detype entier.
Code en C
typedef intelement;
structcellule {
element valeur;
structcellule * suivant;
};
typedef structcellule cellule, * liste;
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Remarque 1:
Notons qu’onpeut cr´eer des listes chaˆın´eescontenant des valeurs qui sont : dediff´erents type, c-`a-d desentiers, desflottants, descaract`eres, destableaux, desstructures,
unecombinaison de plusieurs types, ou deslistes chaˆın´ees.
Exemple :
typedef doubleelement;
structcellule {
element valeur;
structcellule * suivant;
};
typedef structcellule cellule, * liste;
Remarque 2:
Lesinstructionssuivantes permettent de d´eclarer, de fac¸onsdiff´erentesmais´equivalentes, une liste chaˆın´ee : structcellule *l;
cellule *l;
liste l;
Cr´ eation et initialisation
Pourcr´eer une liste chaˆın´ee, on doitl’initialiser`aNULL(macro de stdlib.h), cela va nous permettre d’allouerlapremi`ere cellule.
L’initialisationd’une liste chaˆın´ee, ou lacr´eation d’une liste vide, est g´en´eralement faite par lafonction suivante :
liste creerListeVide( ) {
returnNULL;
}
Pourtestersi une listeest vide, on utilise la fonction suivante :
intListeVide(liste l) {
returnl==NULL;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Insertion d’une cellule (Ajout d’une valeur dans une liste) :
Il est toujours possibled’ins´erer des cellules(ajouter des valeurs) `a une liste chaˆın´ee donn´ee.
En effet,il y a plusieurs fac¸ons d’ajouter des cellulesdans des listes chaˆın´ees : ajouterune nouvelle celluleen tˆetede la liste,
ajouterune nouvelle cellule `ala finde la liste.
ajouterune nouvelle cellule `a unemplacement quelconquedans la liste.
Exemple :Les fonctionsajouterElementTeteListe()etajouterElementFinListe()permettent respectivementl’ajoutd’un ´el´ement entˆeteet `a lafind’une liste.
Ajout d’un ´el´ement en tˆete de la liste listeajouterElementTeteListe(element val, liste l)
{ liste ln;
ln=malloc(sizeof(cellule));
ln->valeur=val;
ln->suivant=l;
returnln;
}
Insertion d’une cellule (Ajout d’une valeur dans une liste) :
Ajout d’un ´el´ement `a la fin de la liste listeajouterElementFinListe(element val, liste l)
{
liste ln,lp;
ln=malloc(sizeof(cellule));
ln->valeur=val;
ln->suivant=NULL;
if(l==NULL) returnln;
lp=l;
while(lp->suivant != NULL) lp= lp->suivant;
lp->suivant =ln;
returnl;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Suppression d’une cellule (supprimer une valeur dans une liste) :
Il est possible ´egalementde supprimer des cellules(des valeurs) dans une liste chaˆın´ee donn´ee.
En effet,il y a plusieurs fac¸ons de supprimer des cellulesdans des listes chaˆın´ees : supprimerune celluleen tˆetede la liste,
supprimerune cellule `ala finde la liste, supprimerune cellulequelconquedans une liste.
Suppression d’un ´el´ement en tˆete de la liste listesupprimerElementTeteListe(liste l)
{ liste lp;
if(l==NULL) returnNULL;
lp=l->suivant;
free(l);
returnlp;
}
Suppression d’une cellule (supprimer une valeur dans une liste) :
Suppression d’un ´el´ement `a la fin de la liste listesupprimerElementFinListe(liste l)
{
liste lp1,lp2;
if(l==NULL) returnNULL;
if(l->suivant==NULL) {
free(l);
returnNULL;
} lp1=l;
while(lp1->suivant->suivant!=NULL) lp1=lp1->suivant;
lp2=lp1->suivant;
lp1->suivant=NULL;
free(lp2);
returnl;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Suppression d’une cellule (supprimer une valeur dans une liste) :
Suppression d’un ´el´ement quelconque dans la liste (M´ethode it´erative) listesupprimerItertiveElementListe(element val, liste l)
{
liste lp1,lp2;
if(l!=NULL) if(l->valeur==val)
{ lp1=l;
l=l->suivant;
free(lp1);
} else
{ lp2=l;
while(lp2->suivant!=NULL && lp2->suivant->valeur!=val) lp2=lp2->suivant;
if(lp2->suivant!=NULL) {
lp1=lp2->suivant;
lp2->suivant=lp2->suivant->suivant;
free(lp1);
} } returnl;
}
Suppression d’une cellule (supprimer une valeur dans une liste) :
Suppression d’un ´el´ement quelconque dans la liste (M´ethode r´ecurrente) listesupprimerRecurrenteElementListe(element val, liste l)
{ liste lp;
if(l!=NULL) if(l->valeur==val)
{ lp=l;
l=l->suivant;
free(lp);
} else
l->suivant=supprimerRecurrenteElementListe(val, l->suivant);
returnl;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Recherche dans une liste :
Etant donn´´ ee une liste chaˆın´eelisteet une valeurval, l’objectif ici estd’effectue un parcoursde liste pourrechercherla valeurvaldansliste. Pour ceci, on peut envisagerdeux types de fonction:
une fonction quitestesi la valeur recherch´eevalfigure dans la listeliste.
une fonction quirenvoie l’adresse de la cellulecontenant la valeur recherch´eeval.
fonctions qui testent sivalfigure dansliste
Recherche dans une liste (M´ethode r´ecurrente) intrechercherRecListe(element val, liste l)
{ if(l==NULL)
return0;
if(l->valeur==val) return1;
returnrechercherRecListe(val, l->suivant);
}
Recherche dans une liste (M´ethode it´erative) intrechercherIterListe(element val, liste l) {
while(l!=NULL) {
if(l->valeur==val) return1;
l=l->suivant;
} return0;
}
Recherche dans une liste :
fonctions quirenvoient l’adresse de la cellulecontenantval
Recherche dans une liste (M´ethode r´ecurrente) listerechercherLRec(element val, liste l)
{ if(l==NULL)
returnNULL;
if(l->valeur==val) returnl;
returnrechercherLRec(val, l->suivant);
}
Recherche dans une liste (M´ethode it´erative) listerechercherLIter(element val, liste L)
{
while(l!=NULL) {
if(l->valeur==val) returnl;
l=l->suivant;
} returnNULL;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par pointeur
Affichage d’une liste :
La fonction suivante permetd’afficher les valeurs stock´eed’une liste.
Affichage d’une liste voidafficherListe(liste l)
{
while(l!=NULL) {
printf("%d ",l->valeur);
l=l->suivant;
} printf("\n");
}
Exercice :
´ Ecrire un programme complet en langage C qui permet de construire une liste chaˆın´ ee,
afficher une liste chaˆın´ ee,
calculer la longueur d’une liste chaˆın´ ee,
rechercher une valeur dans la liste et de retourner sa position dans la liste.
effectuer les manipulations suivantes :
supprimer une valeur quelconque de la liste, supprimer une valeur en d´ ebut de liste, supprimer une valeur en fin de liste,
supprimer une valeur ` a une position donn´ ee dans la liste,
supprimer une valeur avant ou apr` es une position donn´ ee dans la liste.
2.1 Les listes simplement chaˆın´ ees : Implantation par tableau
Une liste peut ˆ etre aussi implant´ ee ` a l’aide d’un tableau.
Les ´ el´ ements de la liste seront donc stock´ es dans les cases contigu¨ es du tableau.
Comme les listes sont des structures de donn´ ees qui g` erent des ensembles dynamiques, une taille maximum pour le tableau doit ˆ etre donc d´ efinie lors des d´ eclarations.
C-` a-d, on ne peut pas modifier la taille maximum du tableau lors de l’ex´ ecution d’un programme.
Et si on d´ esire modifier la taille maximum du tableau, il faut modifier aussi le programme.
Par consequent, il faut d´ efinir un tableau dont la taille sera suffisante pour accueillir la plus grande liste pouvant ˆ etre utilis´ ee!!!
Mais cette d´ emarche peut encombrer la m´ emoire de l’ordinateur.
C’est pourquoi, il est en g´ en´ eral pr´ ef´ erable d’utiliser l’implantation des listes par
des pointeurs.
En langage C, pour implanterune liste chaˆın´ee`a l’aide d’un tableau, on utilise lesstructures.
En effet, lalisteest unobjetconstitu´es :
d’un tableau,detaille suffisantepouraccueillir la plus grande liste`a traiter.
d’un entiercontenantl’indice de la finde la liste. Cet entier contientl’indice+1du dernier ´el´ement de la liste, ou lataille de la liste.
0 1 2 n-1 n Max
2 1 4 0 12
fin
0 1 2 n-1 n Max
2 1 4 0 12
fin
Lad´eclaration correspondanteest la suivante, o`u l’on suppose ici que lesvaleurs stock´eesdans la liste sont detype entier.
Code en C
typedef intelement;
structlisteTab {
element valeur[taille MAX];
intfin;
};
2.1 Les listes simplement chaˆın´ ees : Implantation par tableau
Cr´ eation et initialisation
Pourcr´eer une liste chaˆın´ee, on doitl’initialiser`a untableau de taille nulle.
L’initialisationd’une liste chaˆın´ee, ou lacr´eation d’une liste vide, est g´en´eralement faite par lafonction suivante :
int creerListeVide( ) {
return0;
}
Pourtestersi une listeest vide, on utilise la fonction suivante :
intListeVide(liste l) {
returnl.fin==0;
}
Ajout d’une valeur ` a une liste :
Il est toujours possibled’ajouter des valeurs`a une liste chaˆın´ee donn´ee.
En effet, comme l’implantation par les pointeurs,il y a diff´erentes fac¸ons d’ajouter des valeurs`a une liste chaˆın´ee en particulier on peut
ajouterune nouvelle valeuren tˆetede la liste, ajouterune nouvelle valeur `ala finde la liste.
ajouterune nouvelle valeur `aune position quelconquede la liste.
Ajout d’un ´el´ement en tˆete de la liste listeajouterTeteLTab(element val, liste l)
{ inti;
l.fin=l.fin+1;
for(i=l.fin-1;i>=1;i--) l.valeur[i]=l.valeur[i-1];
l.valeur[0]=val;
returnl;
}
Ajout d’un ´el´ement `a la fin de la liste listeajouterFinLTab(element val, liste l)
{
l.valeur[l.fin]=val;
l.fin=l.fin+1;
returnl;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par tableau
Ajout d’une valeur ` a une liste :
Ajout d’un ´el´ement apr`es une position donn´ee dans la liste liste ajouterApresPosLTab(element val,intpos, liste l)
{ inti;
l.fin=l.fin+1;
for(i=l.fin-1;i>=pos+1;i--) l.valeur[i]=l.valeur[i-1];
l.valeur[pos]=val;
returnl;
}
Ajout d’un ´el´ement apr`es un ´el´ement donn´ee dans la liste listeajouterApresElementLTab(element val, element elem, liste l)
{ inti;
for(i=0;i<l.fin;i++) if(l.valeur[i]==elem)
l=ajouterApresPosLTab(val, i+1, l);
returnl;
}
Suppression d’une valeur dans une liste :
Il est possible ´egalementde supprimer des valeursdans une liste donn´ee.
En effet,il y a diff´erentes fac¸ons de supprimer des valeursdans des listes : supprimerune valeuren tˆetede la liste,
supprimerune valeur `ala finde la liste, supprimerune valeurquelconquedans une liste.
Suppression d’un ´el´ement en tˆete de la liste listesupprimerTeteLTab(liste l)
{ inti;
l.fin=l.fin-1;
for(i=0;i<l.fin;i++) l.valeur[i]=l.valeur[i+1];
returnl;
}
Suppression d’un ´el´ement en fin de la liste listesupprimerFinLTab(liste l)
{
l.fin=l.fin-1;
returnl;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par tableau
Suppression d’une valeur dans une liste :
Suppression d’un ´el´ement quelconque dans une liste listesupprimerElemLTab(element val, liste l)
{ inti,j;
for(i=0;i<l.fin;i++) if(l.valeur[i]==val)
j=i;
l.fin=l.fin-1;
for(i=j;i<l.fin;i++) l.valeur[i]=l.valeur[i+1];
returnl;
}
Suppression d’un ´el´ement quelconque `a une position donn´ee d’une liste
listesupprimerPosLTab(intpos, liste l) {
inti;
l.fin=l.fin-1;
for(i=pos-1;i<l.fin;i++) l.valeur[i]=l.valeur[i+1];
returnl;
}
Recherche dans une liste :
L’objectif ici est derechercherune valeurvaldansliste. Pour ceci, on peut envisagerdeux types de fonction:
une fonction quitestesi la valeur recherch´eevalfigure dans la listeliste.
une fonction quirenvoie la position dans la liste de la valeurcontenant la valeur recherch´eeval.
Tester si la valeur recherch´ee existe dans la liste intrechercherLTab(element val, liste L)
{ inti;
for(i=0;i<l.fin;i++) if(l.valeur[i]==val)
return1;
return0;
}
Rechercher une position d’un ´el´ement d’une liste intrechercherPosLTab(element val, liste L)
{ inti;
if(l.fin==0) return-1;
else
for(i=0;i<l.fin;i++) if(l.valeur[i]==val)
returni+1;
return0;
}
2.1 Les listes simplement chaˆın´ ees : Implantation par tableau
Affichage d’une liste :
La fonction suivante permetd’afficher les valeurs stock´eesd’une liste.
Affichage d’une liste voidafficherLTab(liste l)
{ inti;
if(l.fin<=0)
printf("votre liste est vide!!!\n");
else {
for(i=0;i<l.fin;i++) printf("%d ",l.valeur[i]);
printf("\n\n");
} }