0% ont trouvé ce document utile (0 vote)
23 vues8 pages

Intro Liste

Le document présente les listes chaînées simples et doublement chaînées, expliquant leur structure, mise en œuvre et opérations de base telles que l'insertion, la suppression et le déplacement d'éléments. Les listes chaînées permettent une gestion dynamique de la mémoire, tandis que les listes doublement chaînées offrent la possibilité de parcourir les éléments dans les deux sens. Des exemples de code en C illustrent les concepts abordés.

Transféré par

joujijouji0411
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
23 vues8 pages

Intro Liste

Le document présente les listes chaînées simples et doublement chaînées, expliquant leur structure, mise en œuvre et opérations de base telles que l'insertion, la suppression et le déplacement d'éléments. Les listes chaînées permettent une gestion dynamique de la mémoire, tandis que les listes doublement chaînées offrent la possibilité de parcourir les éléments dans les deux sens. Des exemples de code en C illustrent les concepts abordés.

Transféré par

joujijouji0411
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Listes chaînées simples

Définition

La liste chaînée organise l’information séquentiellement comme dans la structure de


tableau. Chaque maillon/nœud/cellule de la chaîne contient une information et un lien sur le
nœud suivant.
On représentera la liste de la façon suivante :

L’avantage de
8 4 2 1 cette structure par
rapport à la structure
tableau est qu’elle est
deb
dynamique, on peut
8 4 2 1 Null ajouter et retirer des
éléments de la liste à
notre guise, en ayant
une Liste simplement chaînée gestion mémoire
optimale. Il n’est donc
pas nécessaire de connaître à l’avance la taille maximale de la liste.
Mise en oeuvre

Une liste chaînée est une suite de pointeurs sur des objets contenant l’information. La
structure de base d’une liste chaînée est la suivante :

Voici par exemple des éléments, qui ont pour vocation


• de contenir une valeur entière ;
• d'être chainé avec un autre élément.

struct maillon {
int val;
struct maillon *suiv;
};

1 Notions de base : les listes simples

Pour représenter une liste, il nous faut un pointeur sur le premier


élement. Ce pointeur qui sera nul si la liste est vide.

1
struct maillon * deb;

2. Parcours d’une liste (pour effectuer un traitement sur les éléments de la liste).
Nous aurons un pointeur qui contiendra d'abord l'adresse du premier élément (soit deb), puis
du second, etc.

struct maillon *ptr = deb; // adresse du premier (si il existe)


while (ptr != NULL) {
printf("%d\n", ptr->val);
ptr = ptr->suiv; // passage au suivant
}

Ou bien avec la boucle for


for (struct maillon *ptr = deb; ptr != NULL; ptr = ptr->suiv) {
printf("%d\n", ptr->val);
}

3 Pour construire une chaine vide


Au départ, la chaine est vide, le pointeur de début est donc initialisé à NULL.

deb = NULL;

4 Insertion en tête de liste.


Si elle est vide, il faut mettre dans deb l'adresse d'un nouvel Element, créé par malloc,
contenant la valeur souhaitée et qui n'a pas de suivant. Et dire que cet élement est maintenant
le premier de la liste. Soit un code de la forme :
deb

36

if (deb == NULL) {
struct maillon *temp= (struct maillon *)malloc(sizeof (struct maillon));
temp->val = 36;
temp->suiv = NULL;
deb = temp;
}

2. Si la liste n'est pas vide, c'est presque pareil, sauf que le suivant du nouvel Element est l'ancien premier
(qui devient donc le deuxième).

if (deb != NULL) {
struct maillon *temp= malloc(sizeof (struct maillon));
temp->val = 36;
temp->suiv = deb;
deb= temp;

2
}

3. Mais on remarque que le premier cas est "couvert" par le second : si deb est NULL, affecter la
valeur NULL ou celle de deb, c'est la même chose. Donc on n'a pas besoin de tester deb pour séparer
les cas, et on se contente de

// allocation d'un nouvel élément


struct maillon *temp= (struct maillon *)malloc(sizeof (struct maillon)); // 1

// remplissage de l'élément
temp->val = 6;
temp->suiv = deb; // 2

// mise à jour du pointeur de début de liste


deb = temp; // 3

Ci dessous une illustration :


deb

temp 1 2
6
2

5 Insertion en fin de liste.

deb

6
6. Insertion après un élément dans la liste.

deb

3
7. Suppression du premier élément
il faudra libérer le premier élement et mettre à jour le pointeur de début de liste. Mais
attention à procéder dans le bon ordre

struct maillon old = deb;


deb = old->suiv;
free(old);

deb
2 1 8
old
( à libérer)

8. Suppression d’un élément dans la liste

deb

8 4 2 1

9. Suppression d’un élément en fin de la liste élément

deb

6
à libérer

Pour bien comprendre, prenez le temps de faire un dessin avec toutes les étapes.

4
Déplacement
10. Déplacement d’un élément en fin de la liste élément

3 8 4 2 1

3 8 4 2 1

Listes
doublement chaînées
Définition
3 2 8 4 1

Déplacement d’un nœud dans la liste


L’inconvénient des listes simplement chaînées est qu’il n’est possible de les parcourir que dans
un seul sens. Pour qu’il soit possible de les parcourir dans les 2 sens il faut déclarer 2 liens dans la
structure de liste : un pour le nœud suivant et un pour le nœud précédent. C’est ce qu’on appelle une
« liste doublement chaînée ».

La liste utilisée précédemment aurait la représentation graphique suivante :

Mise en œuvre
La liste doublement chaînée
demande un lien supplémentaire par nœud par
8 4 2 1
rapport à la liste simplement chaînée :

La liste doublement chaînée


demande un lien supplémentaire par nœud par
rapport à la liste Liste doublement chaînée simplement chaînée :

En programmation procédurale, il faut utiliser les pointeurs explicite:


Structure Noeud

info

Nœud *Nœud_suivant

Nœud *Nœud_précédent

Par la suite on désignera le nœud suivant par suivant(nœud) et le nœud précédent par
précédent(nœud).

5
La déclaration d’une liste doublement chaînée se fera de la manière suivante :

Début ListeDouble

Variables :

Nœud tete

tete  NIL

Fin ListeDouble

Tous les algorithmes qui suivront sont des fonctions qui doivent être contenues dans
l’algorithme précédent.

Primitives
Déplacement
Le déplacement d’un nœud dans l’arbre nécessite donc la modification de 6 liens (le double
par rapport à une liste simplement chaînée).

Début
3 8 4 2 1

3 8 4 2 1

3 2 8 4 1

Déplacement d’un nœud dans la liste doublement chaînée

Modification(tete,nœud_depart,nœud_fin) // on suppose que nœud_depart est le nœud qu’on veut déplacer,


et nœud_fin, le nœud derrière lequel on veut mettre le nœud choisi. Si nœud_fin est vide on déplace le nœud devant
la tete de liste

Variables locales :

Nœud nœud_choisi

nœud_choisi  nœud_depart

suivant(precedent(nœud_depart))  suivant(nœud_choisi) // si precedent ≠ NIL

6
precedent(suivant(nœud_depart)  precedent(nœud_choisi) // si suivant≠ NIL

Si nœud_fin est vide Alors

suivant(nœud_choisi)  tete

precedent(nœud_choisi)  NIL

precedent(tete)  nœud_choisi

tete  nœud_choisi

Sinon

suivant(noeud_choisi) suivant(nœud_fin)

suivant(nœud_fin)  nœud_choisi

precedent(nœud_choisi)  nœud_fin

precedent(suivant(nœud_choisi))  nœud_choisi

FinSi

Fin Modification

Suppression
On l’aura compris, les différentes primitives pour une liste doublement chaînée demande 2
fois plus de modification sur les liens. Il faut donc modifier 2 liens pour supprimer un élément dans une
liste doublement chaînée.

8 4 2 1
Début

8 4 2 1

8 4 1

Suppression d’un nœud dans la liste doublement chaînée

Suppression(tete,nœud) // on suppose que nœud est le nœud à supprimer

precedent(suivant(nœud))  precedent(nœud) //si suivant ≠ NIL

suivant(precedent(nœud))  suivant(nœud) // si precedent ≠ NIL


Liberer(nœud)

7
Fin Suppression

Insertion

Pour l’insertion il faut modifier 4 liens :

Début 8 4 2 1

8 4 2 1

8 4 2 9 1

Insertion d’un nœud dans la liste doublement chaînée

Insertion(tete,nœud,nœudAInsérer) // on suppose que nœud est le nœud derriere lequel on veut insérer
noeudAInsérer

Si nœud est vide Alors

suivant(noeudAInserer)  tete

precedent(noeudAInserer)NIL

precedent(tete)  noeudAInserer

tete  noeudAInserer

Sinon

precedent(noeudAInserer)  nœud

suivant(nœudAInserer)  suivant(nœud)

suivant(nœud)  noeudAInsérer

precedent(suivant(noeudAInserer))  noeudAInserer // si suivant ≠ NIL

FinSi

Fin Inse

Vous aimerez peut-être aussi