Les Listes Linéaires Chaînées
1- Problématique.
2-Liste simplement chaînée.
3-Définition.
4- Déclaration.
5- Principales fonctionnalités.
6- Listes chaînées particulières.
******************************************************
1- Problématique : Tableau de N éléments
Avantages Inconvénients
Avec un tableau : accès direct à un élément en connaissant son indice.
taille N fixée dans le programme , occupent un espace contiguë.
ajout, suppression n'importe où pas facile et long
2- Liste simplement chaînée :
Soient les déclarations suivantes. Donner le rôle de chacune des séquences d’instructions suivantes : Type
p-Cellule= ^ Cellule Cellule =Enregistrement Info : String Suivant :p-cellule Fin ;
déclaration
Cel1 , Cel2 : p-cellule ;
1- Allouer ( cel1) ; Cel1^. Info ←’samedi’ ; Cel1^. Suivant ←NIL ;
2- Allouer ( cel2) ; Cel2^. Info ←’dimanche’ ; Cel2^. Suivant ←NIL ;
3- Cel1^.
suivant ←Cel2 ;
4- Allouer ( cel2) ;
Cel2^. Info ←’vendredi’ ;
Cel2^. Suivant ←Cel1 ;
Cel1 ←Cel2
3- Définition :
Une liste simple est une suite de nœuds où chacun pointe sur son successeur, sauf le dernier qui pointe sur nil.
Chaque nœud contiendra deux champs :
1. la donnée utile . 2. un lien qui pointera vers l’enregistrement suivant.
Avantages Inconvénients
taille s'adapte exactement au nombre d'éléments ajout, suppression facile et rapide
parcourir la liste pour accéder à un élément.
Le pointeur tête pointe vers le premier nœud de la liste.
4- Déclaration d’une liste : Type p-elm= ^ elm
elm= enregistrement
Valeur : string { ou n’importe quel type}
Suivant : p-elm ; fin ;
Déclaration liste : p-elm ; 5. Principales fonctionnalités :
5.1 Parcours séquentiel (pour affichage par exemple) :L’accès aux nœuds d’une liste est séquentiel :
Procedure Parcours ( UneListe : p-elm);
Déclaration pc : p-elm; { Pointeur Courant } début
pc ← UneListe; { tête de liste } TQ pc <> NIL faire { fin atteinte ? } Traiter (pc^.valeur); { on traite le courant } pc ← pc^.suivant { et on passe au suivant } FinTQ
Fin ;
5.2Insertion en tête (gestion en pile)
Procedure Insertionentete ( VAR debut : p-elm);
déc pn : p-elm;
Val :string ;{ Pointeur Nouveau}
début
allouer (pn); { création nouvel élément } lire (val) ;
pn^.valeur ←val; { sa valeur }
pn^.suivant ← debut; { son suivant = l'ancien premier } debut ← pn { nouveau premier }
Fin;
5.3 Insertion au milieu
Procedure Insertionaumilieu ( avant : p-elm);
Déc pn : p-elm; { Pointeur Nouveau}
Val : string ; début
allouer (pn);
lire ( val) ;{ création nouvel élément } pn^.valeur ← val; { sa valeur }
pn^.suivant ←avant^.suivant; { son suivant = suivant de l'ancien}
avant^.suivant ← pn;
Fin ;
5.4 Procedure InsertionQueue ( avant : p-elm);
Déc pn : p-elm; { Pointeur Nouveau}
Val : string ; début
allouer (pn);
lire ( val) ;{ création nouvel élément } pn^.valeur ← val; { sa valeur }
pn^.suivant ←NIL; { son suivant = NIL}
avant^.suivant ← pn;
Fin ;
Remarque :
Pour ajouter in nouveau nœud à une liste dont les nœuds ne sont pas ordonnés, l’insertion en tête est généralement effectuée.
5.5 Suppression en tête (gestion en pile avec PLUS d'1 ELEMENT)
Procedure Suppressionentete ( VAR debut : p-elm);
déc ps : p-elm; { Pointeur Suppression}
début
ps ←debut; { suppression du 1er }
debut ← ps^.suivant; { nouveau 1er = ancien suivant du 1er } libérer (ps) { récupération de la place }
Fin;
5.6 Suppression au milieu
Procedure Suppressionaumilieu( apres : p-elm);
Déc ps : p-elm ; Début
Ps← apres^.suivant ;
apres^ .suivant ← apres^.suivant^.suivant;
libérer (ps) ; Fin;
5.7 Suppression en queue
Procedure SuppressionaenQueue ( apres : p-elm);
Déc ps : p-elm ; Début
Ps← apres^.suivant ; apres^.suivant ← NIL;
libérer (ps)
Fin
5 .8 Concaténation de deux listes
Ecrire la procédure de concaténation de deux listes liste1 et liste 2 dans une seule liste liste : concat(liste1:pointeur; liste2 pointeur ; var liste:pointeur);
5.9 Eclatement d’une liste :
Ecrire la procédure d’éclatement d’une liste d’entiers en deux listes ; liste1 pour les entiers pairs et liste2 pour les entiers impairs .
6.Listes chaînées particulières 6.1 Les anneaux
Si l'on revient sur l'algorithme "Insertion en queue", on peut remarquer que, pour accélérer l'insertion en fin de chaîne, nous avons été amenés à ajouter un pointeur "fin de chaîne.
Une autre solution consiste à rendre la chaîne circulaire. Cela se fait en remplaçant, dans le dernier élément, le pointeur "Suivant" à nil par un pointeur "Suivant" qui pointe vers le premier élément de la liste. Il est alors plus simple d'avoir un pointeur "Dernier" en lieu et place du pointeur "Début" :
6.1.1. Manipulations sur les anneaux
Les algorithmes d'insertion, de suppression et de parcours d'éléments sont très similaires à ceux que nous avons vus pour les chaînes linéaires. Il faut juste faire attention, lors d'insertion ou de suppression en fin, de mettre correctement à jour le pointeur dernier .
Insertion dans un anneau vide :
if Dernier = nil then begin {anneau vide}
new(Dernier);
with Dernier^ do begin Info := ...;
{ l'él. est son propre succ.}
Suivant := Dernier;
end; { with } end; { if } Parcours d'un anneau :
procedure Parcours(dernier: VersElement; Traite: procedure);
var Courant, premier: VersElement;
begin { Parcours }
if Dernier = nil then { anneau vide } else begin
Premier := Dernier^.Suivant;
Courant:= Premier;
repeat
Traite(Courant); { traitement quelconque à appliquer à chaque élément } Courant := Courant^.Suivant;
until Courant = Premier;
end;
end; { Parcours }
6.2. Les chaînes bidirectionnelles
Si l'on désire souvent pouvoir atteindre des éléments d'une chaîne qui se trouvent quelques positions avant un élément donné, on peut alors adjoindre, à chaque élément, un pointeur supplémentaire vers son prédécesseur.
On obtient alors une chaîne bidirectionnelle :
6.2.1. Manipulations sur les chaînes bidirectionnelles
Insertion en début:
type VersElement = ^Element;
Element = record Info: ...;
Precedent,
Suivant : VersElement;
end; { Element }
procedure InsertionDebut(var Debut: VersElement;Information: ...);
var Nouveau: VersElement;
begin { InsertionDebut } new(Nouveau);
with Nouveau^ do begin Info := Information;
Suivant := Debut;
Precedent := nil;
end; { with }
if Debut <> nil then Debut^.Precedent := Nouveau;
Debut := Nouveau;
end; { InsertionDebut }
Insertion avant un élément donné :
procedure InsertionAvant(var Debut,courant: VersElement; Information: ...);
var Nouveau: VersElement;
begin { InsertionAvant }
new(Nouveau); {création d'un nouvel élément } with Nouveau^ do begin
Info := Information;
Suivant := Courant;
Precedent := Courant^.Precedent;
end; { with }
Courant^.Precedent := Nouveau; { modification des liens des éléments existants } if Debut = Courant then Debut := Nouveau
else Nouveau^.Precedent^.Suivant := Nouveau;
end; { InsertionAvant }
Suppression d'un élément donné :
procedure SuppressionMilieu(var Debut: VersElement; var Courant: VersElement);
begin { SuppressionMilieu } if Courant = Debut then begin Debut := Debut^.Suivant;
if Debut <> nil then
Debut^.Precedent := nil; end else with Courant^ do begin Precedent^.Suivant := Suivant;
if Suivant <> nil then
Suivant^.Precedent := Precedent;
end; { with }
dispose(Courant); { destruction de l'élément courant } end; { SuppressionMilieu }
6.3. Les anneaux bidirectionnels
Une chaîne bidirectionnelle peut, elle aussi, être rendue circulaire. On obtient alors un anneau bidirectionnel:
Cette structure bénéficie des avantages combinés qu'apportent le pointeur "Prédécesseur" et la circularité. Les opérations de suppression d'éléments et les manipulations en fin de chaîne s'en trouvent nettement simplifiées.