Vous êtes sur la page 1sur 7

Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.

dz

Chapitre 1 : les structures de données linéaires:


Une structure de données, est un mécanisme algorithmique, qui permet de définir comment les
informations vont être représentées dans la mémoire de la machine.
Selon le problème qu’on cherche à modéliser, il est important de définir une structure de données
qui sera utilisée comme représentation de ces informations, et via laquelle nos programmes vont
l’utiliser pour appliquer des opérations (tris, ajout, effacement, stockage etc).
En algorithmique, il existe plusieurs types de de structure de données, on peut les catégoriser en
deux familles : Structure de données linéaires, Structure de données hiérarchiques.
La première famille contient des structures de données comme les liste, les piles, les files. Elle
permet de représenter les informations sous forme d’un ensemble d’éléments de même types, et
l’accès à ces éléments se fait d’une façon linéaire. Chaque élément contient une (ou plusieurs
informations) mais doit impérativement contenir l’information qui concerne la localisation de
l’élément qui le suit, et donc l’adresse dans la mémoire d’un autre élément.
Dans le monde physique on trouve beaucoup de phénomène ou système qui peuvent être
représentés sous forme d’une liste. On peut citer comme exemple :
 Liste de trams dans un train : tram A attaché à un autre tram B et ainsi de suite
 Liste des étudiants: Karim, Adel, Ali.
 Liste des mots dans un texte, voir même liste de caractères qui forme un mot
 Liste des instructions dans un plan GPS: Tourner à gauche, aller tout droit à 100 m, tourner à
droite etc.
 -Liste de stage dans un jeu.

Les stratégies de représentation d’une liste chaînée :


Le concept le plus simple qui nous vient en tête quand on parle de liste, c’est les tableaux. Comme
on décrit dans le chapitre révision, un tableau est un ensemble de cellule dans la mémoire de la
machine, on peut dedans stocker des informations de même types. On peut imaginer le cas d’un
tableau d’entiers ou de chaîne de caractères. On peut accéder au contenu de chaque cellule via son
indice dans le tableau.
Mais dans certain cas un tableau ne peut pas résoudre notre problème, pour les limitations
suivantes:
• La taille du tableau est définie lors de sa déclaration, donc si on ne sait pas à l’avance le
nombre des éléments, ceci posera un problème.
• Les opération d’insertion / Suppression prennent beaucoup de temps, car elles nécessitent
des décalages. Car pour vider une cellule dans un tableau il faut qu’on décale toute les
cellules qui viennent après, de même pour l’insertion, si on veut insérer un élément dans une
cellule précise, on doit impérativement décaler tous les éléments de position après.
Pour résoudre ce problème on a recours au liste chaînée qui sont une structure dynamique. Car sa
taille est théoriquement illimitée (en réalité elle est limitée par la taille de la mémoire de la
machine), l’ajout d’un élément se fait d’une façon dynamique (à la demande, on utilise que
lorsqu’on a besoin, et a toute moment on peut libérer l’espace mémoire).
Définition :
En algorithmique, une liste chaînée (linked list en anglais) c’est une structure de données composée
des éléments de même type, dont chacun possède : un ou plusieurs champs contenant des
informations, un champ de type pointeur qui contient l’adresse de l’élément qui le suit (son
successeur). Le chaînage consiste à stocker dans les champs de type pointeur, les adresses d’une
façon qu’à la fin on arrive à former une liste, comme schématisée dans la figure suivante :
20
Page
Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

Figure : schéma d’une liste simplement chaînée


Comme noté sur le schéma, l’adresse du premier élément est stocker dans une variable de type
adresse (pointeur) elle servira comme entrée pour accéder au reste de la liste.
Il est à noter aussi que le dernier élément ne possède pas d’élément qui le suit, et pour marquer la
fin de la liste, une constante spéciale NULL est utilisée.

Déclaration d’une liste simplement chaînée ( Simply Linked


List)

En algorithmique : En langage C :
Type Element = Enregistrement typedef struct Element {
Val : Entier ; int val ;
Suivant: Liste ; struct Element* suivant ;
Fin } * Liste ;
Liste=^Element ;
Listing : Déclaration d’une liste en ALGO et en C
Comme on peut remarquer, rappelez-vous, chaque élément de notre liste regroupe ici deux
informations, et comme on sait déjà, pour regrouper des informations ensemble on doit utiliser les
enregistrements. Ce qui nous permet de déclarer notre propre type, ici on lui a affecté le nom
Element, donc la liste est un ensemble d’éléments de type enregistrement dont chacun possède
deux champs : un champs contenant une information (ici de type entier), et un champs de type Liste
qui est une adresse de l’élément qui le suit.

Les opérations sur les listes :


Après avoir définie la structure d’une liste, il est important de savoir comment on peut lui appliquer
les opérations de base. Si on a une liste on peut lui faire :
• Créer la liste (si notre liste et vide ceci veux dire que la variable Tête contient la valeur
NULL), après cette opération elle contiendra l’adresse de premier élément crée.
• Supprimer un élément de la liste
• Chercher si un élément d’une valeur donnée, figure ou non dans la liste.
• Modifier un élément, le localiser et modifier sa valeur.
1- Création d’une liste :
Pour créer une liste on doit simplement insérer les éléments l’un après l’autre, bien sûr l’adresse du
premier élément doit être gardé dans une variable de type adresse (qu’on l’appelle communément
tête ou Head en anglais). Quand on insère les éléments, on peut choisir d’insérer en tête (donc le
dernier élément sera placé en tête de liste) ou bien en queue de liste (dans ce cas le premier élément
inséré sera gardé en tête).
Comme décrit dans le listing ci-dessus, l’algorithme de création reçoit en entrée un paramètre
21

contenant l’adresse du premier élément, bien sûr au départ ce paramètre contient la valeur NULL.
Après exécution de l’algorithme, il produit en sortie dans le paramètre tête l’adresse de l’élément
Page

créé.
Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

Procédure Insert( Var Tête : Liste, e : entier) ;


var newElm:Liste ;
début
new(newElm)
newElm^.val=e ;
if( tête == NULL)
newElm^.suivant=NULL ;
tête= newElm
else
p=tête ;
while(p^.suivant!=NULL)p=p^.suivant ;
p^.suivant=newElm;
fin;
Listing : Insertion d’un élément dans une liste simplement chaînée

Parcourir une liste simplement chaînée


Une fois qu’on a une liste créée, on peut lui appliquer plusieurs opérations, la plupart de ces
opérations nécessitent le parcours des éléments de la liste. Pour faire cela, la technique la plus
simple est l’utilisation d’une boucle avec une variable de type pointeur. La boucle répètera le bloc
d’instructions et vérifie à chaque fois une condition d’arrêt. La condition de la boucle doit
impérativement impliquer la variable utilisée dans le parcours. Il est à noter que, lorsqu’on veut
traiter tous les éléments de la boucle on parcourt jusqu’à ce que la variable de la boucle est égale à
NULL. Si on veut s’arrêter quand on arrive au dernier élément de la liste on teste sur le champ
suivant de l’élément pointé par la variable de parcours. Si on suppose qu’on a une variable de
parcours nommée P :
 Condition pour traiter tous les éléments de la liste : P!=NULL
 Condition pour s’arrêter au dernier élément de la liste P^.suivant !=NULL.
 Dans le bloc d’instructions de la boucle on doit à chaque fois modifier la variable de
parcours pour passer à l’élément suivant comme suit : P=P^.suivant.
Le listing qui suit, montre comment une liste simplement chainée peut-être parcouru et affichée.

pocédure parcourirListe( tête:liste) ;


début
while(tete!=NULL)
début
print(tête^.val) ;
tête=tete^.suivant ;
fin
fin
Listing parcourir une liste

2-Supression d’un élément d’une liste :


Cette opération permet de retirer un élément de la liste, comme décrit dans le listing, cet algorithme
doit prendre en considération quatre possibilités :
A) La liste est vide, et donc l’algorithme s’arrête sans rien faire.
B) L’élément à supprimer n’existe pas dans la liste, et de même l’algorithme s’arrête sans rien
faire.
22

C) L’élément à supprimer se trouve dans la tête de la liste, dans ce cas on doit retirer cet
Page

élément et modifier la tête pour qu’elle pointe sur l’élément qui le suit.
Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

D) L’élément à supprimer se trouve à la fin de la liste, dans ce cas on retire l’élément et on


modifier le champs « suivant » de son prédécesseur et dedans on mit la valeur NULL pour
marquer la fin de la liste.
E) L’élément se trouve au milieu de la liste, dans ce cas avant de retirer l’élément, on doit
mettre à jour le chainage pour que l’élément qui le précède pointe sur l’élément qui le suit.

Procédure suprimer (var tête, e : entier) ;


var temp,p,q:Liste ;
début
if(tête!NULL) (le cas A)
début
if(tête^.val==e) début
p=tête ;
tête=tête^.suivant ; (le cas A)
free(p) ;
else début
p=tête ;
q=tête^.suivant ;
while((p!=NULL)&&(p^.val!=e)
debut
q=p ;
p=p^.suivant ;
fin
if(p!=NULL) début
temp=p ;
q^.suivant=p^.suivant ;
free(temp) ;
fin
fin
fin
Listing suppression d’un élément d’une liste

3- Vérifier l’existence d’un élément dans la liste :


Parfois, on a besoin de vérifier si un élément contenant une valeur donnée figure dans la liste ou
non. Cette opération produit une valeur booléen, vrai si l’élément existe faux si non. Comme décrit
dans le listing suivant :

Fonction Existe ( Tête : Liste, e:entier):boolean ;


var trouver : boolean ;
début
if( Tête==NULL) return false ;
else
while( tête!=NULL)&& (tête^.val!=e) tête=tête^.suivant ;
if (tête==NULL) return false ;
else return true ;
Fin,
Listing fonction de vérification de l’existence d’un élément dans une liste

Modifier la valeur d’un élément dans la liste :


23
Page
Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

procédure modifier ( tete : Liste, E:entier, nouvelValeurlE : entier) ;


début
while ( tête!=NULL) && (tête^.val!=E)
tête=tête^.suivant ;
if ( tête!=NULL) tête^.val=nouvelValeurlE ;
fin
Listing procédure modifier un élément dans une liste

Liste doublement chaînée :


Dans une liste simplement chaînée, chaque élément possède l’adresse de son successeur. Il existe
une autre variante dont laquelle chaque élément possède l’adresse de son successeur et aussi de son
prédécesseur. Ce type de liste est nommée « Liste Doublement Chaînée ». Comme schématisé dans
la figure suivante :

Figure : schéma d’une liste doublement chaînée

Structure de données d’une liste doublement chaînée :


Type Element=Enregistrement
Val : entier ;
suivant:ListeDoublementChaînée ;
précédent :ListeDoublementChaînée ;
fin
ListeDoublementChaînée =^Element ;
Listing déclaration d’une liste doublement chaînée

Le principal avantage d’une liste doublement chaînée est qu’on peut la parcourir selon deux sens,
aussi les opérations d’ajout et de suppression sont plus simples, car le chaînage peut être mis à jour
facilement, car chaque élément possède un pointeur sur son prédécesseur.
Parcours d’une liste doublement chainée :

Procédure Parcourir1(tête:ListeDoublementChainée) ;
début
while(tête!=NULL)
début
Print(tête^.val) ;
tête=tête^.suivant ;
fin
fin
Listing Parcourir une liste doublement chaînée.
24

On peut aussi parcourir la même liste à l’inverse.


Page
Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

procédure Parcourir2 (tête:ListeDoublementChainée) ;


début
p=tête ;
while(p^.suivant!=NULL)p=p^.suivant ;
while(p!=NULL)
début
print(p^.val)
p=p^.precedent ;
fin
fin
Listing Parcourir une liste doublement chaînée.

Les opérations de base sur une liste doublement chaînée :


1- Insertion d’un élément dans une liste doublement chaînée, cette opération peut avoir lieu soit en
début donc en tête de liste ou bien à la fin de liste.
Dans le listing suivant, on trouve comment insérer un élément en tête.

Procédure InsertionEnTête(var tête:ListeDoublementChaînée, e : entier) ;


var p:ListeDoublementChaînnée ;
début
new(p) ;
p^val=e ;
p^.suivant=tête ;
tête=p ;
p^.précédent=NULL ;
fin
Listing d’insertion d’un élément dans une liste doublement chaînée, en tête.
Et dans le listing suivant on trouve comment insérer un élément à la fin d’une liste doublement
chaînée.

Procédure InsertionListeDoublement(var ListeDoublementChaînnée, e:entier) ;


var p,q:ListeDoublementChaînée ;
début
new(p)
p^.val=e ;
p^.suivant=NULL ;
p^.precedent=NULL ;
if(tête==NULL) tête=p ;
else début
q=tête ;
while(q^.suivant!=NULL) q=q^.suivant ;
q^.suivant=p ;
p^.précedent=q ;
fin
fin
Listing d’insertion d’un élément dans une liste doublement chaînée, en Queue.
25

Dans le cas d’une liste doublement chaînée, lorsque l’élément en tête de liste contient l’adresse de
dernier élément, et ce dernier possède l’adresse de premier élément, la liste dans ce cas est une liste
Page

doublement chaînée circulaire. ( voir le schéma sur la figure)


Université Badji Mokhtar , Annaba, Département d’Informatique, L2, ALGO-STD-2, sabri.ghazi@univ-annaba.dz

Figure : schéma d’une liste doublement chaînée circulaire


Comme peut être vu sur le schéma, on a :
• Le marqueur NULL n’est plus utilisé, car le dernier élément possède un successeur, qui est
le premier élément.
• Si on veut parcourir la liste, la boucle doit itérer jusqu’à ce qu’on revient au premier
éléments.

Insertion d’un élément dans une liste doublement chainée circulaire.

Procédure Insertion ( var tête:listDoublementChaînée, e : Entier) ;


début
if(tête==NULL)
new(p) ;
p^.suivant=p ;
p^.precedent=p ;
else
p^.suivant=tête ;
tête^.precedent^.suivant=p ;
p^.précédent=tête^.precedent ;
tête^.precedent=p ;
fin
fin
Listing : Insertion dans une liste doublement chaînée circulaire
26
Page

Vous aimerez peut-être aussi