edubun
Français

Les listes chaînées

Ajouter une valeur au début d'une liste chaînée modifie deux pointeurs, que la liste contienne 4 valeurs ou 4 millions.

Des valeurs qui pointent vers la suivante

Un tableau garde ses valeurs côte à côte, et c'est pour cela que modifier le début coûte cher. Une liste chaînée abandonne cette règle. Chaque valeur vit dans son propre petit enregistrement appelé nœud, et les nœuds peuvent se trouver n'importe où en mémoire. Les notes du cours 6.006 du MIT décrivent un nœud avec deux champs : l'élément, et next, un pointeur vers le nœud suivant. La liste elle-même ne retient que le premier nœud, appelé la tête (head). Le next du dernier nœud vaut null, ce qui marque la fin.

Pour lire la liste, on part de head et on suit les pointeurs next un par un, comme on suivrait une série de messages indiquant chacun où est caché le suivant. Cela a un coût. Il n'existe pas de formule pour l'adresse du quatrième nœud : obtenir la valeur à la position i oblige donc à visiter i + 1 nœuds. Le MIT indique que get at(i) est en O(n) pour une liste chaînée, alors que le tableau le faisait en une étape.

// un nœud par valeur : { value, next }
let head = null;
for (const v of [4, 30, 7, 12]) head = { value: v, next: head };
// parcourir la liste
for (let n = head; n !== null; n = n.next) console.log(n.value); // 12, 7, 30, 4

Modifier la liste en refaisant les liens

L'avantage apparaît quand on modifie la liste. Pour placer une nouvelle valeur au début, on crée un nœud dont le next est la tête actuelle, puis on fait pointer head vers le nouveau nœud. Deux changements de pointeur, et rien d'autre ne bouge. Supprimer le premier nœud demande un seul changement : faire pointer head vers head.next. Compare avec le tableau, où les mêmes opérations déplaçaient toutes les valeurs.

Au milieu, le travail consiste à trouver l'endroit. Pour insérer à la position i, on avance jusqu'au nœud juste avant (i visites), puis on fait les deux mêmes changements de pointeur : new.next = prev.next, puis prev.next = new. L'ordre compte. Si l'on modifie prev.next en premier, le reste de la liste est perdu, car plus rien ne pointe vers lui. Dans le labo, une étape est un nœud visité ou un pointeur modifié : insérer à la position 2 d'une liste de 4 nœuds coûte donc 2 visites plus 2 changements, soit 4 étapes.

Chargement

Fais glisser pour tourner. Fais défiler ou pince pour zoomer.

Une liste simplement chaînée de quatre nœuds. Choisis une position avec le curseur et insère ou supprime ; le compteur sépare les nœuds visités des pointeurs modifiés. Chercher avance depuis head jusqu'à rencontrer la valeur ou null.
OpérationTableau (n valeurs)Liste chaînée (n nœuds)
Obtenir la valeur à la position i1i + 1 visites
Insérer au débutn déplacements + 1 écriture2 changements de pointeur
Supprimer le début1 lecture + (n − 1) déplacements1 changement de pointeur
Insérer à la position i(n − i) déplacements + 1 écriturei visites + 2 changements
Trouver une valeurjusqu'à n lecturesjusqu'à n visites

Quand l'utiliser

Une liste chaînée convient bien quand la plupart des modifications ont lieu à un endroit vers lequel on a déjà un pointeur, comme le début, et qu'on a rarement besoin de la position i. On peut construire des files et des piles avec des listes chaînées, et aussi les chaînes d'une table de hachage, dans l'unité suivante. Il existe des variantes. Une liste doublement chaînée donne aussi à chaque nœud un pointeur prev : on peut alors parcourir la liste à l'envers et supprimer un nœud en une étape une fois qu'on l'a. Garder un pointeur tail en plus de head rend l'ajout à la fin bon marché.

En JavaScript de tous les jours, on écrit rarement une liste chaînée, car les tableaux sont bien optimisés et les caches des processeurs modernes favorisent les valeurs stockées côte à côte. L'idée compte quand même : les arbres, les graphes et de nombreuses structures des bibliothèques sont construits exactement ainsi, avec des nœuds et des pointeurs.

ContexteLes listes chaînées sont apparues au milieu des années 1950 avec l'Information Processing Language (IPL), écrit par Allen Newell, Cliff Shaw et Herbert Simon à la RAND Corporation et au Carnegie Institute of Technology vers 1956. Leurs programmes cherchaient des démonstrations de théorèmes de logique, et le nombre et la taille des choses à retenir ne pouvaient pas être connus à l'avance. Des listes de cellules chaînées permettaient de distribuer et de reprendre la mémoire une cellule à la fois. Le traitement de listes d'IPL a influencé Lisp, que John McCarthy a conçu quelques années plus tard.
  1. Quels sont les deux champs d'un nœud de liste simplement chaînée ?
    • item et next
    • index et value
    • left et right
    • head et tail
  2. Liste 12 → 7 → 30 → 4. Combien d'étapes demande l'insertion d'une nouvelle valeur au début (changements de pointeur) ?
  3. Même liste : insérer à la position 2 coûte combien d'étapes (visites plus changements de pointeur) ?
  4. Même liste : combien de nœuds visite une recherche de 30 ?
  5. Même liste : combien de nœuds visite une recherche de 99 avant d'atteindre null ?
  6. Même liste : supprimer le nœud à la position 3 (le 4) coûte combien d'étapes ?
  7. Un tableau contient 1000 valeurs et a de la place libre. Combien d'étapes demande l'insertion au début ?
  8. Quelle tâche convient mieux à une liste chaînée qu'à un tableau ?
    • Lire de nombreuses fois la valeur à la position 500
    • Ajouter et retirer de nombreuses fois au début
    • La recherche dichotomique
    • Trier par indice
  9. Pour insérer après le nœud p, quel ordre des étapes conserve le reste de la liste ?
    • p.next = new, puis new.next = p.next
    • new.next = p.next, puis p.next = new
    • Les deux ordres fonctionnent
    • Supprimer p d'abord
  10. Quel langage, écrit vers 1956 à la RAND, a introduit le traitement de listes avec des cellules chaînées ?
    • Fortran
    • IPL
    • C
    • JavaScript
L'essentiel
  • Une liste chaînée stocke chaque valeur dans un nœud doté d'un pointeur next ; la liste garde head.
  • Insérer ou supprimer au début modifie 1 ou 2 pointeurs ; rien ne bouge.
  • Atteindre la position i demande i + 1 visites : get at(i) est donc en O(n).
  • Règle new.next avant de refaire le lien du nœud précédent.
Sources de ce cours (11)
  • MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
  • lecture notes 2 Data Structures (interface vs data structure, Sequence and Set interfaces, stack = insert_last/delete_last, queue = insert_last/delete_first, array, linked list, dynamic array, amortized Θ(1) append)
  • 4 Hashing (chaining, pigeonhole collisions, chain length n/m)
  • 6 Binary Trees Part 1 (height, traversal order, O(h) operations) and 7 Binary Trees Part 2: AVL (Adelson-Velsky and Landis, 1962) at ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes
  • MDN Web Docs, Array.prototype.shift (shifts all values left by 1)
  • Array.prototype.unshift, Map (insertion order, Map vs Object, spec requires sublinear average access) and Set (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
  • ECMAScript 2025 Language Specification (tc39.es/ecma262)
  • 24.1 Map Objects and 24.2 Set Objects ("must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements")
  • Array.prototype.shift steps (Repeat, while k < len: move element k to k - 1)
  • D. E. Knuth, The Art of Computer Programming vol. 3 (2nd ed. 1998) section 6.4 History (H. P. Luhn, IBM internal memorandum January 1953, hashing with chaining; digit pairs added mod 10, 31415926 -> 4548) via gwern.net copy, and IEEE Spectrum, "Hans Peter Luhn and the Birth of the Hashing Algorithm" (2018)
  • "A brief history of the stack", SIGCIS (sigcis.org/files/A brief history.pdf: Bauer and Samelson applied for the patent in 1957, US 3,047,228 granted July 31, 1962; IPL list processing by Newell, Simon and Shaw at RAND 1956) and Wikipedia, Information Processing Language (Newell, Shaw, Simon, RAND and Carnegie Institute of Technology, about 1956).

Consulté le: 2026-10-18