Vous êtes sur la page 1sur 20

Chap4_ASD2 FST LCS1

Chapitre 4 : Les listes chaînées


I- Introduction

La « liste chaînée » est une structure de données linéaire à accès indirect qui n'a pas de
dimension fixée à sa création. Ses éléments de même type sont éparpillés dans la mémoire et
reliés entre eux par des pointeurs. Sa dimension peut être modifiée selon la place disponible
en mémoire. La liste est accessible uniquement par sa tête de liste c’est-à-dire son premier
élément. Pour ajouter, supprimer ou déplacer un élément il suffit d'allouer une place en
mémoire et de mettre à jour les pointeurs des éléments.

Il existe plusieurs types de listes chaînées:


• Les listes chaînées simples où à partir d’un élément on peut accéder à l’élément
suivant.
• Les listes chaînées doubles où à partir d’un élément on peut accéder aussi bien à
l’élément suivant qu’à l’élément précédent.
• Les listes chaînées circulaires ou bouclées où le dernier élément pointe sur le
premier élément de la liste. S'il s'agit d'une liste doublement chaînée alors le
premier élément pointe également sur le dernier.

Partie 1- Les listes simplement chaînées


I. Définition

Une liste simplement chaînée est une suite d’un nombre variable de cellules (enregistrements)
de même type liées entre elles par des pointeurs: chaque cellule, sauf la dernière, pointe vers
son successeur. Il suffit de connaître le pointeur du début de la liste (tête) pour accéder aux
différents autres éléments de la liste.
Chaque cellule (enregistrement) contient 2 champs :
• L’information utile.
• Un pointeur qui pointera vers la cellule (enregistrement) suivante.

Il faut conserver une "trace" du premier enregistrement afin de pouvoir accéder aux autres :

1 / 20
Chap4_ASD2 FST LCS1

• c'est pourquoi un pointeur vers le premier élément de la liste est indispensable. Ce


pointeur est appelé pointeur de tête.
• Le dernier enregistrement ne pointe vers rien. Il est donc nécessaire de donner à son
pointeur la valeur NULL (Nil).
• Dans le cas d'une liste vide le pointeur de la tête contient la valeur Nil.
• Une liste est définie par l'adresse de son premier élément.
II. Déclaration :

La structure de donnée qui permet de représenter une liste simplement chaînée dans le cas
général est déclarée comme suit :

Type

Cellule = enregistrement

valeur : type

suivant : ^Cellule //Ou suivant : Liste

FinEnregistrement

Liste : ^Cellule

Var

Tête : Liste // c’est le pointeur tête

Le type Cellule qui est un enregistrement formé de deux champs : un qui contient la valeur de
l’élément donc le type peut être un type quelconque et le 2ème champ (suivant) contient un
pointeur vers la cellule suivante. C'est-à-dire il contient l’adresse de la cellule suivante. La
dernière cellule ne pointe vers rien donc elle doit contenir la valeur Nil.

Le type Liste est un pointeur sur Cellule qui contient l’adresse du 1er élément de la liste.

Exemple :

• Le 1er élément de la liste vaut 12 à l'adresse 3 (début de la liste chaînée)


• Le 2ème élément de la liste vaut 14 à l'adresse 4 (car le pointeur de la cellule d’adresse
3 est égal à 4)
2 / 20
Chap4_ASD2 FST LCS1

• Le 3ème élément de la liste vaut 10 à l'adresse 2 (car le pointeur de la cellule d’adresse


4 est égal à 2)
• Le 4ème élément de la liste vaut 24 à l'adresse 1 (car le pointeur de la cellule d’adresse
2 est égal à 1)
• Si un pointeur P a pour valeur 3, P^.valeur a pour valeur 12 et P^.suivant a pour valeur
4

III- Manipulation des listes simplement chaînées

Pour simplifier on va travailler sur une liste dont le champ « valeur » est de type entier. Alors
la définition du type liste sera comme suit :

Type

Cellule = enregistrement

valeur : entier

suivant : ^Cellule

FinEnregistrement

Liste : ^Cellule

Var

Tête :Liste

1. Création d’une liste simplement chaînée vide (initialisation) :

La première procédure de base qu’on doit écrire pour pouvoir manipuler des données de type
liste est la procédure Init( ) qui prend en entrée une liste Tête et l’initialise en liste vide.

Procédure Init (VAR Tête : Liste)

Début

Tête NIL

Fin

3 / 20
Chap4_ASD2 FST LCS1

2. Tester si une liste simplement chaînée est vide :

La fonction ListeVide ( ) qui prend en entrée une liste et retourne vrai si elle est vide et faux
sinon.

Fonction ListeVide (Tête : Liste) : Booléen

Début

Si (Tête = NIL) Alors

ListeVide ← Vrai

Sinon

ListeVide ← Faux

FinSi

Fin

3. Dernier élément d’une liste simplement chaînée :

La fonction PosFin ( ) prend en entrée une liste et retourne un pointeur vers le dernier élément
de la liste.

Fonction PosFin (Tête : Liste) : Liste

Var

P : Liste

Début

P← Tête

Si (P < > NIL) Alors

Tantque (P^.suivant < > Nil) Faire

P←P^.suivant

Fintanque

FinSi

PosFin←P

Fin

4 / 20
Chap4_ASD2 FST LCS1

4. Taille d’une liste simplement chaînée :

Version itérative Version Récursive


Fonction Taille_Liste(Tête : Liste) : entier Fonction Taille_Liste(Tête : Liste) : entier
Début Début
Si ( Tête = NIL ) Alors Si (Tête=NIL) Alors
Taille_Liste ← 0 Taille_Liste ← 0
Sinon Sinon
Taille_Liste ← 0 Taille_Liste ← 1 +Taille_Liste(Tête^.suivant)
Tant que ( Tête < > NIL) faire Finsi
Taille_Liste ← Taille_Liste + 1 Fin
Tête ← Tête^.suivant
Fintantque
Fin Si
Fin

5. Ajout d’un élément dans une liste simplement chaînée:


Ajout en tête

La procédure AjouterTête ( ) prend en entrée une valeur à ajouter en tête d’une liste donnée.

Cette procédure doit créer une nouvelle variable dynamique pour contenir la nouvelle cellule,
puis remplir le champ valeur et le champ suivant de cette cellule ensuite mettre l’adresse de
cette cellule dans le pointeur pointant sur la tête de liste (Tête).

Procédure AjouterTête (x : entier, VAR Tête : Liste)

Var

NouvCell : Liste

Début

Allouer (NouvCell)

NouvCell ^.valeur ← x

Si (Tête=NIL) Alors //Liste vide

NouvCell ^.suivant ← NIL

Tête← NouvCell

5 / 20
Chap4_ASD2 FST LCS1

Sinon

NouvCell ^.suivant ← Tête

Tête← NouvCell

FinSi

Fin
Ajouter un élément à la fin d’une liste

La procédure AjouterFin() prend en entrée une valeur à ajouter à la fin d’une liste donnée ;

Procédure AjoutFin(VAR Tête : Liste, x :entier) Procédure AjoutFin_V2(VAR Tête : Liste, x :entier)
Var Var
NouvCell, P : Liste NouvCell, P : Liste
Début Début
Allouer (NouvCell) Allouer (NouvCell)
NouvCell^.valeur← x NouvCell^.valeur←x
NouvCell ˆ.suivant← NIL NouvCell ˆ.suivant←NIL
Si ListeVide(Tête) Alors //cas où la liste est Si ListeVide(Tête) Alors //cas où la liste est
vide vide
Tête ← NouvCell Tête ← NouvCell
Sinon //cas où la liste n’est pas vide Sinon //cas où la liste n’est pas vide
P ← Tête P ←PosFin(Tête)
Tantque(Pˆ.suivant< >NIL) faire Pˆ.suivant← NouvCell
P ← Pˆ.suivant FinSi
Fintanque
Fin
Pˆ.suivant← NouvCell
FinSi
Fin

Ajouter un élément au milieu d’une liste

Cette procédure permet l’insertion d’une nouvelle cellule après une position donnée en
paramètre sachant que cette cellule n’est pas la dernière dans la liste.

6 / 20
Chap4_ASD2 FST LCS1

Procédure AjoutMilieu(VAR position: Liste, x :entier)


Var
NouvCell : ^Cellule
Début
Allouer (NouvCell)
NouvCell^.valeur ← x
NouvCellˆ.suivant ← positionˆ.suivant
positionˆ.suivant← NouvCell
Fin
6. Chercher un élément dans une liste :

Cette fonction permet de rechercher un élément dans une liste. Elle renvoie la position de
l’élément x s’il existe et NIL s’il n’existe pas.

Version itérative Version récursive


Fonction rechercher(x : entier, Tête : Liste) Fonction rechercher(x : entier, Tête: Liste) :
: Liste
Liste
Var Début
Si (Tête = NIL) Alors
P : Liste
rechercher← NIL
Début SinonSi (Tête^.valeur=x) Alors
rechercher← Tête
P ← Tête
sinon
Tantque (P < > NIL ET P^.valeur < >x) rechercher← rechercher(x,Tête^.suivant)
P ← P^.suivant FinSi

Fintantque Fin
rechercher← P
Fin

7. Suppression d’un élément d’une liste simplement chaînée:

Suppression d’un élément en tête

7 / 20
Chap4_ASD2 FST LCS1

Procédure SupprimerTête (VAR Tête : Liste)

VAR

P : Liste

DEBUT

Si( ListeVide(Tête) = Faux) Alors

P ← Tête

Tête ←Tête^.suivant

LIBERER (P)

P ← NIL

FinSi

FIN

Suppression d’un élément à la fin d’une liste

Procédure SupprimerFin (VAR Tête : Liste)

VAR

P : Liste

Début

Si( ListeVide(Tête) = Faux) Alors

Si (Tête ^. suivant = NIL) Alors //càd on a 1 seule cellule dans la liste

LIBERER (Tête)

Tête ← NIL

Sinon

8 / 20
Chap4_ASD2 FST LCS1

P ← Tête

Tant que ( (P ^. suivant) ^. suivant < > NIL) faire

P ← P^. suivant

Fin Tant que

LIBERER (P^.suivant)

P^. suivant ← NIL

Fin Si

Fin Si

FIN

Suppression d’un élément donné d’une liste simplement chaînée

Procédure Supprimer (x : entier, VAR Tête : Liste)


VAR
P, position: Liste
DEBUT
position ← rechercher(x,Tête)
Si (position < > NIL) Alors
Si (position = Tête) Alors //x est le premier élément
SupprimerTête (Tête : Liste)
Sinon Si (position^.suivant = NIL) Alors //x est le dernier élément
SupprimerFin (Tête : Liste)
Sinon //x est au milieu de la liste
P Tête
Tantque (P^.suivant < > position) Faire
P P^.suivant
FinTantque
P^.suivant position^.suivant
LIBERER(position)
position NIL
FinSi
Sinon
Ecrire (« Elément à supprimer non existant »)
FinSi
Fin

9 / 20
Chap4_ASD2 FST LCS1

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

Version itérative Version récursive

Procédure AFFICHE_Liste (Tête : Liste) Procédure AFFICHE_Liste (Tête : Liste)


VAR Début
P: Liste Si (Tête < > NIL) Alors
Début Ecrire (Tête^.valeur)
P ← Tête AFFICHE_Liste (Tête^. suivant)
Si (P= NIL) Alors Ecrire ("Liste vide ") Fin Si
Sinon Fin
Tantque ( P< > Nil) Faire
Ecrire (P^.valeur)
P ← P^.suivant
Fin Tant que
FinSi
Fin

Partie 2 - Les listes doublement chaînées


I- Introduction

Dans les listes vues précédemment le parcours ne peut se faire que dans un seul sens : de la
tête vers la queue. Pour remédier à cette dissymétrie de l’opération et permettre un parcours
aussi bien dans un sens que dans l’autre, on peut construire des listes doublement chaînées (ou
listes bilatères ou listes bidirectionnelles)

II- Définition

Une liste doublement chaînée comporte deux pointeurs qu’on appelle « précédent» et
«suivant ». Si un élément a un prédécesseur, il est désigné par le pointeur « précédent », s’il a
un successeur, il est désigné par le pointeur « suivant ». Cette structure permet de parcourir la
liste dans les 2 sens et d’accélérer la recherche d’un élément.

• Si Tête = Queue = Nil ⇒ La liste est vide


• Si Tête = Queue ≠ Nil ⇒ La liste a un seul élément

10 / 20
Chap4_ASD2 FST LCS1

• Le pointeur précédent du premier élément ainsi que le pointeur suivant du dernier


élément contiennent la valeur Nil.
III- Déclaration

TYPE
Cellule = enregistrement
précédent : ^Cellule
valeur : entier
suivant : ^Cellule
Fin enregistrement
ListeDC = ^Cellule

VAR
Tête,Queue : ListeDC

IV- Manipulation des listes doublement chaînées :


1- Initialisation d'une liste doublement chaînée :
A l'initialisation d'une liste doublement chaînée les pointeurs Tête et Queue contiennent la
valeur Nil.
Procédure init (VAR Tête, VAR Queue: ListeDC)
Début
Tête NIL
Queue NIL
Fin

2- Ajout d'un élément à une liste doublement chaînée :


Ajout d'un élément à la tête d’une liste doublement chaînée

Procédure ajout_tête (x : entier, VAR Tête, VAR Queue : ListeDC)


Var
P : ListeDC
Début
Allouer (P)

P^.valeur ←x

P^.précédent ←NIL
Si (Tête = NIL) Alors //Liste vide

P^.suivant ← NIL

Tête← P

11 / 20
Chap4_ASD2 FST LCS1

Queue←P
Sinon //Liste n’est pas vide

P^.suivant ← Tête

Tête^.précédent ← P

Tête ← P
Fin si
Fin

Ajout d'un élément en queue d’une liste doublement chaînée

Procédure ajout_en_queue(x : entier, VAR Tête, VAR Queue : ListeDC )


Var
P : ListeDC
Début
Allouer(P)
P^.valeur x
P^.suivant NIL
Si Tête = NIL Alors //Liste vide
P^.précédent NIL
Tête P
Queue P
Sinon

Queue^.suivant P

P^.précédent Queue
Queue P
Fin Si
Fin

Ajout d'un élément au milieu d’une liste doublement chaînée


Procédure inserer_après (x : entier, VAR position: ListeDC, VAR Tête:
ListeDC)

12 / 20
Chap4_ASD2 FST LCS1

Var
P: ListeDC
Début
Allouer (P)

P^.valeur ← x

P^.suivant ← position^.suivant

P^.précédent ← position

(position^.suivant)^.précédent ← P

position^.suivant ← P
Fin

3- Recherche d’un élément dans une liste doublement chaînée

La fonction recherche permet de vérifier si l’élément x existe dans la liste. Elle renvoie la
position de l’élément x s’il existe et NIL s’il n’existe pas.

Fonction Recherche (x : entier, Tête : ListeDC ) : ListeDC


Var
P : ListeDC
Début
P ← Tête
Tantque (P < > NIL ET P^.valeur < > x) Faire
P ← P^.suivant
FinTantque
Recherche P
Fin

4- Suppression d'un élément d’une liste doublement chaînée


Procédure Supprimer (x : entier, VAR Tête, VAR Queue: ListeDC)
Var
Position: ListeDC
Début
position ← Recherche (x,Tête)
Si (position < > NIL) Alors
Si position = Tête ET position= Queue Alors // Liste à 1 seul élément
Liberer (position)
Tête ← NIL

13 / 20
Chap4_ASD2 FST LCS1

Queue ← NIL
Sinon Si position = Tête Alors // Supprimer l’élément en tête
Tête ← Tête^.suivant
Tête^.précédent ← NIL
Liberer(position)

position ← NIL
Sinon Si position = Queue Alors // Supprimer le dernier élément
(Queue^.précédent)^.suivant ← NIL

Queue ←Queue^.précédent
Liberer (position)

position ← NIL
Sinon // l’élément à supprimer est au milieu
(position^.précédent)^.suivant ← position^.suivant
(position^. suivant) ^. précédent ← position^. précédent
Libérer (position)

position ← NIL
FinSi
Sinon
Ecrire (« L’élément à supprimer n’existe pas »)
FinSi
Fin

5- Afficher les éléments d'une liste doublement chaînée


Il est possible d’afficher les éléments de la liste doublement chaînée du premier élément
vers le dernier. Le pointeur de parcours, P, est initialisé avec l'adresse contenue dans « Tête ».
Il prend les valeurs successives des pointeurs « suivant » de chaque élément de la liste. Le
parcours s'arrête lorsque le pointeur de parcours a la valeur Nil. Cet algorithme est analogue à
celui du parcours d'une liste simplement chaînée.

Procedure AfficherListe (Tête : ListeDC)


Var
P : ListeDC
DEBUT
P Tête
Tantque(P < > NIL) FAIRE
Ecrire (P^.valeur)
P P^.suivant
FinTantque
FIN

14 / 20
Chap4_ASD2 FST LCS1

Il est possible d’afficher les éléments de la liste doublement chaînée du dernier élément
vers le premier. Le pointeur de parcours, P, est initialisé avec l'adresse contenue dans
« Queue ». Il prend les valeurs successives des pointeurs « précédent » de chaque élément de
la liste. Le parcours s'arrête lorsque le pointeur de parcours a la valeur Nil.

Procedure AfficherListeInverse (Queue : ListeDC)


Var
P : ListeDC
Début
P Queue
Tantque (P < > NIL) FAIRE
Ecrire(P^.valeur)
P P^.précédent
FinTantque
Fin

Partie 3 – Les listes chaînées circulaires


I- Définition
La liste chaînée circulaire est une liste simplement ou doublement chaînée, qui comporte
une caractéristique supplémentaire pour le déplacement dans la liste, "elle n'a pas de fin".
Pour rendre la liste sans fin, le pointeur « suivant » du dernier élément pointera sur le 1er
élément de la liste au lieu de la valeur NIL, que nous avons vu dans le cas des listes
simplement et doublement chaînées.
Dans les listes circulaires, en arrivant au dernier élément, le déplacement recommencera au
premier élément. En bref, il s'agit d'une rotation.
Ci-dessous l'exemple d'une liste simplement chaînée circulaire : le dernier élément pointe
sur le premier.

Puis l'exemple d'une liste doublement chaînée circulaire. : Le dernier élément pointe sur le
premier, et le premier élément pointe sur le dernier.

15 / 20
Chap4_ASD2 FST LCS1

II- Déclaration
La cellule est la même que pour une liste chaînée simple ou double non circulaire. Le
parcours se fait à partir de n'importe quelle adresse de maillon (cellule) contenue dans le
pointeur « Courant » jusqu'à retrouver cette même adresse.
III- Manipulation des listes simplement chaînées circulaires
1. Initialisation
Procédure Init(VAR Courant : Liste)
Début
Courant NIL
Fin

2. Ajout d’un élément


Pour ajouter un élément nous avons besoin du pointeur courant. La valeur de son suivant
va changer c'est pourquoi il doit être passé par variable afin de ne pas perdre la modification.
L'algorithme est le suivant :
• Si le pointeur courant est NIL c'est que la liste est vide dans ce cas le nouvel élément
donne son adresse à courant.
• Sinon, il y a au moins un élément dans la liste, peut-être plusieurs. Alors le nouvel
élément prend pour suivant le suivant de l'élément courant et l'élément courant prend
pour suivant le nouvel élément.
Procédure Ajouter ( x : entier, VAR Courant : Liste )
Var
NouvCell : Liste
Début

Allouer (NouvCell)

NouvCell ^.valeur ← x

Si Courant=NIL Alors //Liste vide


Courant ←NouvCell

NouvCell ^.suivant ← NouvCell

Sinon //Liste non vide

NouvCell ^.suivant ← Courant^.suivant

Courant^.suivant ← NouvCell

FinSi

Fin

16 / 20
Chap4_ASD2 FST LCS1

3. Suppression

De même que pour ajouter, pour supprimer un élément, il nous faut le pointeur courant.
L’élément à supprimer se trouve après l'élément courant.

Pour supprimer un élément dans la liste, tout d'abord, il faut vérifier que la liste n'est pas
vide et puis il faut considérer ces situations :

• Suppression dans une liste avec un seul élément


• Suppression dans une liste avec plusieurs éléments
Procédure Supprimer (VAR Courant : Liste)

Var

AS : Liste

Début

Si (Courant < > NIL) Alors //Liste non vide

Si (Courant^.suivant = Courant) Alors // Liste avec 1 seul élément

Libérer(Courant)

Courant NIL

Sinon

AS Courant ^.suivant

Courant^.suivant AS^.suivant

Libérer(AS)

AS NIL

FinSi

FinSi

Fin

4. Affichage
Si la liste n'est pas vide, pour parcourir et afficher la liste à partir du maillon « Courant »,
nous avons besoin de conserver l'adresse contenue dans ce maillon courant afin de pouvoir la
reconnaître et savoir que le parcours est terminé. Nous n'utilisons pas le pointeur « Courant »
pour ce parcours mais un autre pointeur « P » qui prend la valeur de « Courant » au départ. La

17 / 20
Chap4_ASD2 FST LCS1

valeur de « Courant » ne bouge donc pas. On s’arrête lorsque la fin de la liste est arrivée, c'est
à dire si P= Courant.

Procédure Affichage (Courant : Liste)


Var
P : Liste
Début
Si (Courant = NIL) Alors
Ecrire (« La liste est vide »)
Sinon
P Courant
Répéter
Ecrire (P^.valeur)
P P^.suivant
Jusqu’à (P = Courant)
FinSi
Fin

IV- Manipulation des listes doublement chaînées circulaires


1. Initialisation
Procédure Init (VAR Courant : ListeDC)
Début
Courant NIL
Fin

2. Ajout d’un élément


Procédure Ajouter ( x : entier, VAR Courant : ListeDC )
Var
NouvCell : ListeDC
Début

Allouer (NouvCell)

NouvCell ^.valeur ← x

Si Courant=NIL Alors //Liste vide


Courant ←NouvCell

NouvCell ^.suivant ← NouvCell

NouvCell ^.précédent ← NouvCell

18 / 20
Chap4_ASD2 FST LCS1

Sinon //Liste non vide

NouvCell ^.précédent ← Courant

NouvCell ^.suivant ← Courant^.suivant

(NouvCell^.suivant)^.précédent ← NouvCell

Courant ^.suivant ← NouvCell

FinSi

Fin

3. Suppression

Pour supprimer il nous faut le pointeur courant. L’élément à supprimer se trouve après
l'élément courant.

Procédure Supprimer (VAR Courant : ListeDC)

Var

AS : ListeDC

Début

Si (Courant < > NIL) Alors //Liste non vide

Si (Courant^.suivant = Courant) Alors // Liste avec 1 seul élément

Libérer(Courant)

Courant NIL

Sinon

AS Courant ^.suivant

Courant^.suivant AS^.suivant

(AS^.suivant)^.précédent Courant

Libérer(AS)

AS NIL

FinSi

FinSi

19 / 20
Chap4_ASD2 FST LCS1

Fin

4. Affichage

Procédure Affichage (Courant : ListeDC)


Var
P : ListeDC
Début
Si (Courant = NIL) Alors
Ecrire (« La liste est vide »)
Sinon
P Courant
Répéter
Ecrire (P^.valeur)
P P^.suivant
Jusqu’à (P = Courant)
FinSi
Fin

20 / 20

Vous aimerez peut-être aussi