Aller au contenu

Numérique et sciences informatiques (spécialité) · TerminaleBac

Les listes chaînées : cours de Terminale NSI

Publié le 7 novembre 2026 · Mis à jour le 7 novembre 2026 · Signaler une erreur

L'essentiel

  • Une liste chaînée est une suite de cellules ; chaque cellule contient une donnée et un lien vers une autre cellule 2.
  • On ne connaît que la tête : pour atteindre un élément, on suit les liens un par un depuis le début, sans accès direct par indice.
  • Ajouter ou retirer en tête ne modifie qu'un ou deux liens ; le piège est de perdre la référence vers la suite avant de l'avoir sauvegardée.
  • Une liste simplement chaînée se parcourt dans un seul sens, une liste doublement chaînée dans les deux 3.
  • Le parcours s'écrit avec une variable courant qui avance tant qu'elle n'est pas None.

Pourquoi une nouvelle structure de données ?

Tu connais déjà la liste Python : on écrit t[3] et on obtient directement le quatrième élément. Tu l'utilises sans te demander comment elle est rangée dans la mémoire de l'ordinateur. En Terminale, on change de point de vue : on construit soi-même des structures de données avec des objets, pour comprendre ce qu'elles coûtent et à quoi elles servent.

La liste chaînée est la première de ces structures. Elle te sert ensuite de modèle pour les piles, les files et les arbres, qui reposent sur la même idée : des objets qui se référencent les uns les autres.

En informatique, une liste est un type de données abstrait qui regroupe des données de façon à pouvoir y accéder librement, contrairement aux piles et aux files, dont l'accès est imposé (LIFO ou FIFO) 3. La liste sert de base à des types plus complexes comme la pile, la file ou les arbres 3.

Pour bien situer l'intérêt, comparons avec le tableau. Les données d'un tableau sont contiguës en mémoire, ce qui impose une taille fixe 3. Certains langages de haut niveau proposent des tableaux dont la taille varie, comme la liste Python : ils restent rangés d'un seul bloc en mémoire et, quand la place manque, ils sont recopiés dans une zone plus grande. À l'inverse, la taille d'une liste chaînée n'est limitée que par la mémoire disponible : pour l'agrandir, il suffit de créer une nouvelle cellule et de faire pointer vers elle une cellule déjà présente 3.

Anatomie d'une liste chaînée

Une cellule est un petit objet à deux composantes : la valeur qu'elle transporte et le lien vers la cellule suivante. Autrement dit, en plus de sa donnée, chaque élément porte une référence qui le relie à un voisin dans la liste 2.

Représentons la liste 2→7→4→92 \to 7 \to 4 \to 9 :

tête → [ 2 | • ] → [ 7 | • ] → [ 4 | • ] → [ 9 | None ]

Chaque rectangle est une cellule : à gauche la valeur, à droite le lien. La dernière cellule ne pointe vers rien : son lien vaut None. C'est ce None qui signale « la chaîne s'arrête ici ». Une liste vide, elle, est une tête qui vaut directement None.

Ajouter un élément en têteTrois étapes : créer la cellule, la relier à l'ancienne tête, la déclarer nouvelle tête.1CréerOn crée une nouvelle cellule contenant la valeur.2RelierSon lien suivant désigne l'ancienne tête.3DéclarerLa tête de la liste désigne la nouvelle cellule.
  1. CréerOn crée une nouvelle cellule contenant la valeur.
  2. RelierSon lien suivant désigne l'ancienne tête.
  3. DéclarerLa tête de la liste désigne la nouvelle cellule.
Ajouter un élément en tête · L'ordre des étapes évite de perdre la suite de la chaîne.

Construisons à la main la liste 2→7→42 \to 7 \to 4, en commençant par la fin :

c3 = Cellule(4)          # dernière cellule, suivant = None
c2 = Cellule(7, c3)      # 7 pointe vers 4
c1 = Cellule(2, c2)      # 2 pointe vers 7
l = Liste()
l.tete = c1

Les trois variables c1, c2, c3 ne servent qu'à construire : une fois la liste faite, seule l.tete compte. Avec l.tete.suivant.valeur, on obtient 7.

Parcourir une liste chaînée

Comme on ne connaît que la tête, on ne peut pas sauter directement au milieu. Pour voir tous les éléments, on suit les liens de cellule en cellule. C'est l'opération de base : presque tout le reste en dérive.

Voici le calcul de la longueur, méthode de la classe Liste :

def longueur(self):
    n = 0
    courant = self.tete
    while courant is not None:
        n += 1
        courant = courant.suivant
    return n

Sur la liste vide, courant vaut None dès le départ, la boucle ne s'exécute pas et on renvoie 0. Sur 2→7→42 \to 7 \to 4, la boucle tourne trois fois.

Pour accéder au i-ième élément (les indices commencent à 0), on avance ii fois :

def acces(self, i):
    courant = self.tete
    for _ in range(i):
        if courant is None:
            raise IndexError("indice trop grand")
        courant = courant.suivant
    if courant is None:
        raise IndexError("indice trop grand")
    return courant.valeur

Il faut suivre ii liens avant d'arriver sur la bonne cellule. Plus l'indice est grand, plus le trajet est long. C'est la grande différence avec t[i] sur un tableau, où l'on tombe directement sur la case.

Le même parcours s'écrit de façon récursive, ce qui rejoint la définition récursive de la structure : une liste est soit vide, soit une cellule suivie d'une liste. Les listes chaînées s'appuient justement sur une définition récursive, chaque élément pointant vers d'autres éléments de la liste 3.

def longueur_rec(cellule):
    if cellule is None:
        return 0
    return 1 + longueur_rec(cellule.suivant)

Le cas de base est la chaîne vide (None), le cas récursif traite la première cellule puis la suite.

Ajouter un élément

Ajouter un élément revient à créer une cellule et à réarranger quelques liens. La difficulté n'est pas de coder, mais de choisir l'ordre des affectations.

On recommande souvent la liste chaînée quand l'ordre des éléments compte et qu'on insère ou retire des éléments n'importe où plus souvent qu'on ne les consulte 2. C'est cohérent avec ce que tu viens de voir : insérer ne coûte que quelques liens, alors qu'accéder demande de parcourir.

Supprimer un élément

Supprimer, c'est court-circuiter une cellule : on fait pointer sa précédente directement vers sa suivante. La cellule oubliée n'est plus référencée par personne, elle n'appartient plus à la liste.

Listes doublement chaînées et listes circulaires

Avec un seul lien par cellule, impossible de reculer. On peut enrichir la cellule.

La cellule possède alors trois attributs :

class CelluleD:
    def __init__(self, valeur):
        self.valeur = valeur
        self.suivant = None
        self.precedent = None

Cette souplesse a un prix. Il faut stocker un lien de plus par cellule, donc davantage de mémoire, et les mises à jour demandent plus d'instructions : insérer une cellule recopie quatre pointeurs, là où deux suffisent dans une liste simplement chaînée 2.

Trois sortes de listes chaînées
TypeLiens par celluleParcours
Simplement chaînéeUn (suivant)Un seul sens
Doublement chaînéeDeux (suivant, précédent)Deux sens
CirculaireSelon le typeBoucle sans début ni fin
Trois sortes de listes chaînées · D'après la description des types de listes chaînées.

Liste chaînée ou liste Python ?

En Terminale, on te demande régulièrement de justifier le choix d'une structure : liste Python, dictionnaire, pile, file, arbre, graphe… et d'expliquer en quoi elle est adaptée à l'exercice 1. Voici de quoi argumenter sur les listes.

Une remarque sur Python lui-même : la liste Python (list) n'est pas une liste chaînée au sens de ce cours. Elle s'utilise avec des indices, et on distingue ses opérations, une question classique à l'épreuve pratique 1 : par exemple, tab.append(i) modifie la liste existante, alors que tab = tab + [i] construit une nouvelle liste. De même, sorted(tab) renvoie une nouvelle liste triée, tandis que tab.sort() trie tab sur place. Quand tu écris ta propre classe Liste, tu dois donc programmer explicitement ces opérations.

Un peu d'histoire pour terminer. Les listes chaînées ont été conçues en 1955-1956 par Allen Newell, Cliff Shaw et Herbert Simon, de RAND Corporation 2. Elles formaient la structure de base de leur langage IPL, utilisé pour développer des programmes d'intelligence artificielle 2. Le langage Lisp, dont le nom vient de list processing, repose lui aussi sur la liste 3.

Exercices corrigés

Exercice 1 Lire une liste après plusieurs opérations

★☆☆Environ 8 min

On part d'une liste vide. On exécute dans l'ordre :

l = Liste()
l.ajouter_en_tete(4)
l.ajouter_en_tete(7)
l.ajouter_en_tete(2)
l.ajouter_en_queue(9)

Quelle est la valeur de l.acces(2) (indices à partir de 0) ?

Indice 1

Dessine la liste après chaque instruction : l'ajout en tête place l'élément avant tous les autres.

Indice 2

L'ajout en queue place 9 après le dernier élément.

Voir la correction pas à pas
  1. Après ajouter_en_tete(4) : la liste est 44.

  2. Après ajouter_en_tete(7) : on place 7 devant, la liste est 7→47 \to 4.

  3. Après ajouter_en_tete(2) : la liste est 2→7→42 \to 7 \to 4.

  4. Après ajouter_en_queue(9) : la liste est 2→7→4→92 \to 7 \to 4 \to 9.

  5. L'indice 0 est 2, l'indice 1 est 7, l'indice 2 est 4. On suit deux liens depuis la tête.

l.acces(2) vaut 4. Le piège est de croire que le premier élément ajouté (4) reste en tête : l'ajout en tête le repousse vers la fin.

Exercice 2 Écrire une fonction de comptage

★★☆Environ 15 min

Écris une méthode compter(self, x) de la classe Liste qui renvoie le nombre de cellules dont la valeur est égale à x. Précise ce qu'elle renvoie sur une liste vide, puis applique-la à la liste 3→5→3→33 \to 5 \to 3 \to 3 avec x=3x = 3.

Indice 1

Utilise le même schéma de parcours que pour longueur, avec un compteur.

Indice 2

Ne touche à aucun lien : ici on lit seulement.

Voir la correction pas à pas
  1. On initialise un compteur n = 0 et courant = self.tete.

  2. Tant que courant is not None, on compare courant.valeur à x ; si égalité, on ajoute 1 à n.

  3. À chaque tour, on avance avec courant = courant.suivant, sinon la boucle est infinie.

  4. À la fin de la boucle, on renvoie n.

  5. Sur la liste vide, la boucle ne s'exécute pas et la méthode renvoie 0. Sur 3→5→3→33 \to 5 \to 3 \to 3, trois cellules valent 3, donc la méthode renvoie 3.

def compter(self, x):
    n = 0
    courant = self.tete
    while courant is not None:
        if courant.valeur == x:
            n += 1
        courant = courant.suivant
    return n

Le résultat sur l'exemple est 3.

Exercice 3 Supprimer toutes les occurrences

★★★Environ 20 min

Écris une méthode supprimer_tout(self, x) qui retire de la liste toutes les cellules de valeur x, et renvoie le nombre de cellules supprimées. Fais-la fonctionner sur : liste vide, x en tête (plusieurs fois de suite), x à la fin, x absent.

Indice 1

Traite d'abord les têtes égales à x avec une boucle, avant de parcourir le reste.

Indice 2

Pour le reste, garde une référence à la cellule courante et teste courant.suivant, sans avancer quand tu supprimes.

Voir la correction pas à pas
  1. On initialise n = 0.

  2. Tant que la tête existe et vaut x, on exécute self.tete = self.tete.suivant et on incrémente n. Cela règle le cas « plusieurs x au début ».

  3. Si la liste est maintenant vide, on renvoie n. Sinon, courant = self.tete.

  4. Tant que courant.suivant n'est pas None : si courant.suivant.valeur == x, on écrit courant.suivant = courant.suivant.suivant et on incrémente n, sans avancer (la nouvelle suivante peut aussi valoir x). Sinon, on avance.

  5. On renvoie n.

def supprimer_tout(self, x):
    n = 0
    while self.tete is not None and self.tete.valeur == x:
        self.tete = self.tete.suivant
        n += 1
    if self.tete is None:
        return n
    courant = self.tete
    while courant.suivant is not None:
        if courant.suivant.valeur == x:
            courant.suivant = courant.suivant.suivant
            n += 1
        else:
            courant = courant.suivant
    return n

Le point délicat est de ne pas avancer après une suppression : deux x consécutifs seraient sinon mal traités.

Quiz

7 questions · correction immédiate · ton score reste sur ton appareil.

  1. Que contient une cellule d'une liste simplement chaînée ?

  2. Dans une liste simplement chaînée, que vaut le lien de la dernière cellule ?

  3. Dans une liste simplement chaînée, on peut accéder à la cellule d'indice 50 sans passer par les précédentes.

  4. Quelle instruction ajoute correctement v en tête de la liste l ?

  5. Quelles affirmations sur les listes doublement chaînées sont vraies ?

    Plusieurs réponses possibles.

  6. Une liste chaînée contient 8 cellules. On cherche une valeur absente. Combien de cellules examine-t-on avec le parcours habituel ?

  7. Dans l'insertion après une cellule c, quel est le bon ordre ?

Les questions qu'on se pose

À quoi servent les listes chaînées si Python a déjà des listes ?

À comprendre comment une structure se construit avec des objets, et à servir de base à d'autres structures. La liste est à l'origine de types plus complexes comme la pile, la file ou les arbres 3. À l'épreuve pratique, on peut te demander d'expliquer en quoi une structure est adaptée à un exercice donné 1.

Quelle différence y a-t-il entre `None` et une liste vide ?

Dans la classe Liste de ce cours, la liste est vide quand tete vaut None ; None est la valeur du lien de fin. La liste est un objet (qui existe), None est l'absence de cellule. Cela explique pourquoi on teste self.tete is None pour savoir si la liste est vide, et non self is None.

Pourquoi mon parcours plante avec une erreur sur `None` ?

Tu as écrit un accès comme courant.suivant.valeur alors que courant.suivant valait None, ou tu as continué à avancer après la dernière cellule. Vérifie la condition de ta boucle : while courant is not None pour traiter toutes les cellules, while courant.suivant is not None pour s'arrêter sur la dernière. Pense aussi au cas de la liste vide.

Comment tester mes fonctions sur les listes chaînées ?

Écris des assertions sur les cas particuliers : liste vide, une seule cellule, premier ou dernier élément concerné, valeur absente, doublons 1. Tu peux écrire une méthode qui convertit la liste chaînée en liste Python, pour comparer facilement le résultat attendu avec assert.

Y a-t-il une limite au nombre de cellules d'une liste chaînée ?

La seule limite est la mémoire disponible : pour agrandir la liste, il suffit de créer une cellule et de faire pointer une cellule existante vers elle 3. C'est une différence avec un tableau de taille fixe, dont les données sont contiguës en mémoire 3.

Sources

  1. Ressources IREM - Structures de données NSI, Académie de Lyon. Consulté le 7 novembre 2026.
  2. Liste chaînée, Wikipédia. Consulté le 7 novembre 2026.
  3. Liste (informatique), Wikipédia. Consulté le 7 novembre 2026.

Les numéros dans le texte renvoient à ces sources. Une source qui ne dit pas ce qu'on lui fait dire ? Signale-le.

Signaler une erreur sur cette page

Je suis en…

Primaire

  • CP Bientôt
  • CE1 Bientôt
  • CE2 Bientôt
  • CM1 Bientôt
  • CM2 Bientôt

Collège

Lycée

Supérieur

  • BTS Bientôt
  • BUT Bientôt
  • Licence Bientôt
  • Prépas Bientôt

Sur cette page