Numérique et sciences informatiques (spécialité) · TerminaleBac
Listes chaînées : exercices corrigés 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, chacune contenant une donnée et un pointeur vers une autre cellule 2.
- Dans une liste simplement chaînée, on ne parcourt que dans un sens ; dans une liste doublement chaînée, on peut aller dans les deux sens 3.
- Pour parcourir : une boucle
while courante is not Noneetcourante = courante.suivant. - Pour insérer ou supprimer : modifier des pointeurs, dans le bon ordre, sans déplacer les autres cellules.
- Pour accéder à un élément d'indice k, il faut suivre k pointeurs depuis la tête : l'accès n'est pas direct.
Comment utiliser ces exercices
Ces exercices s'adressent à toi si tu prépares l'épreuve de NSI en Terminale et que tu as déjà manipulé des classes en Python. Cherche d'abord seul·e, sur papier : dessine des boîtes et des flèches avant d'écrire la moindre ligne de code. La plupart des erreurs sur les listes chaînées viennent d'un schéma qui n'a pas été fait.
Tous les exercices utilisent cette classe. Une liste est représentée par sa tête, c'est-à-dire la première cellule ; la liste vide est représentée par None.
class Cellule:
def __init__(self, valeur, suivant=None):
self.valeur = valeur
self.suivant = suivant
La liste s'écrit : tete = Cellule(4, Cellule(8, Cellule(15))). La dernière cellule a suivant égal à None.
Les exercices
Exercice 1 Lire et parcourir une liste
On construit la liste suivante :
tete = Cellule(4, Cellule(8, Cellule(15, Cellule(16))))
def somme(tete):
total = 0
courante = tete
while courante is not None:
total = total + courante.valeur
courante = courante.suivant
return total
- Dessine la liste avec ses cellules et ses pointeurs.
- Quelle valeur renvoie
somme(tete)? - Que renvoie
somme(None)?
Indice 1
Fais un tableau de suivi avec les colonnes courante.valeur et total à chaque tour de boucle.
Indice 2
Pour somme(None), regarde si la condition du while est vraie dès le départ.
Voir la correction pas à pas
Schéma :
None. La dernière cellule ne pointe vers rien.Avant la boucle :
total = 0etcourantedésigne la cellule de valeur 4.Tour 1 :
totalvaut 4, puiscourantepasse sur 8. Tour 2 :totalvaut 12. Tour 3 :totalvaut 27. Tour 4 :totalvaut 43, puiscourantevautNone.La condition
courante is not Noneest fausse : la boucle s'arrête et la fonction renvoie 43.Pour
somme(None):courantevautNonedès le départ, la boucle ne s'exécute pas et la fonction renvoie 0.
Le parcours d'une liste chaînée suit toujours le même modèle : on part de la tête, on traite la cellule courante, puis on avance avec suivant jusqu'à rencontrer None. Ce modèle fonctionne aussi pour la liste vide sans cas particulier.
Exercice 2 Compter les pointeurs
Une liste contient 7 éléments.
- Combien de pointeurs
suivantcontient-elle si elle est simplement chaînée (on compte aussi le pointeur de la dernière cellule, égal àNone) ? - Si la liste est doublement chaînée, chaque élément dispose d'un pointeur vers son successeur et d'un pointeur vers son prédécesseur 3. Combien de pointeurs la liste contient-elle au total ?
- Quel est l'inconvénient mémoire de la version doublement chaînée ?
Indice 1
Chaque cellule porte le même nombre de pointeurs : multiplie par le nombre de cellules.
Voir la correction pas à pas
Liste simplement chaînée : chaque cellule porte un seul pointeur, vers le suivant 3. Avec 7 cellules : 7 pointeurs.
Liste doublement chaînée : chaque cellule porte 2 pointeurs 3. Avec 7 cellules : pointeurs.
Conséquence : la structure doublement chaînée est plus coûteuse en mémoire, car elle demande un pointeur supplémentaire par élément 2.
Ce que l'on gagne en confort (parcours dans les deux sens), on le paie en mémoire et en travail de mise à jour des pointeurs. Le choix d'une structure est toujours un compromis.
Exercice 3 Écrire une fonction de longueur
- Écris une fonction
longueur(tete)qui renvoie le nombre de cellules d'une liste chaînée, sans utiliser de tableau Python. - Écris des assertions qui testent les cas particuliers : liste vide, liste d'une cellule, liste de trois cellules 1.
- Propose une version récursive de la même fonction.
Indice 1
Utilise un compteur initialisé à 0 et incrémenté à chaque cellule rencontrée.
Indice 2
Pour la version récursive, la longueur de la liste vide est 0, et celle d'une liste non vide est plus la longueur de la liste qui commence à tete.suivant.
Voir la correction pas à pas
Version itérative : on part de
courante = teteetn = 0, on boucle tant quecourante is not Noneen ajoutant 1 ànet en avançant.def longueur(tete): n = 0 courante = tete while courante is not None: n = n + 1 courante = courante.suivant return nAssertions :
assert longueur(None) == 0,assert longueur(Cellule(5)) == 1,assert longueur(Cellule(1, Cellule(2, Cellule(3)))) == 3.Version récursive : le cas de base est la liste vide, le cas général s'appuie sur la sous-liste qui suit.
def longueur_rec(tete): if tete is None: return 0 return 1 + longueur_rec(tete.suivant)Les deux versions visitent chaque cellule une fois : le nombre d'opérations est proportionnel à la longueur de la liste.
La liste chaînée se prête naturellement à la récursivité, car la liste qui suit la tête est elle-même une liste chaînée. Cette définition récursive est justement ce qui permet à la taille de la liste de ne dépendre que de la mémoire disponible 3.
Exercice 4 Combien de copies de pointeurs ?
Insérer un élément dans une liste doublement chaînée coûte quatre copies de pointeurs, contre deux pour une liste simplement chaînée 2.
- Explique pourquoi une insertion au milieu d'une liste simplement chaînée demande deux affectations de pointeurs.
- On insère 5 éléments dans une liste doublement chaînée. Combien de copies de pointeurs au total ?
- Combien aurait-on fait de copies avec une liste simplement chaînée ?
Indice 1
Pour la question 1, nomme les deux pointeurs concernés : celui de la nouvelle cellule et celui de la cellule qui la précède.
Voir la correction pas à pas
Insertion de
naprèscdans une liste simple :n.suivant = c.suivant(la nouvelle cellule pointe vers la suite), puisc.suivant = n(la précédente pointe vers la nouvelle). Deux affectations.Liste doublement chaînée : 4 copies par insertion. Pour 5 insertions : copies.
Liste simplement chaînée : 2 copies par insertion. Pour 5 insertions : copies.
La structure doublement chaînée double le travail de mise à jour à chaque insertion. Elle se justifie si le parcours à rebours est réellement utile.
Exercice 5 Insérer en tête et après une cellule
- Écris
inserer_tete(tete, v)qui renvoie la nouvelle tête après insertion devau début. - Écris
inserer_apres(c, v)qui insère une cellule de valeurvjuste après la cellulec(supposée nonNone). - Un élève propose :
n = Cellule(v)
c.suivant = n
n.suivant = c.suivant
Que se passe-t-il ? Dessine le résultat.
Indice 1
Dans l'insertion en tête, il n'y a qu'une seule création de cellule et aucune boucle.
Indice 2
Dans le code de l'élève, regarde la valeur de c.suivant au moment de la dernière ligne.
Voir la correction pas à pas
Insertion en tête : la nouvelle cellule pointe vers l'ancienne tête, et elle devient la nouvelle tête.
def inserer_tete(tete, v): return Cellule(v, tete)Insertion après
c: on garde d'abord la suite en la faisant pointer par la nouvelle cellule, puis on rattache.def inserer_apres(c, v): c.suivant = Cellule(v, c.suivant)Analyse du code de l'élève : après
c.suivant = n, la valeur d'origine dec.suivantest perdue. La dernière ligne devientn.suivant = ncarc.suivantdésigne maintenantn.Résultat : la nouvelle cellule pointe vers elle-même. Elle forme une boucle infinie, et toute la fin de la liste d'origine est inaccessible.
Règle à retenir : on branche d'abord la nouvelle cellule sur la suite, puis on modifie le pointeur de la cellule précédente. L'ordre des affectations compte autant que leur contenu.
Exercice 6 Supprimer la première occurrence
Écris une fonction supprimer(tete, v) qui supprime la première cellule de valeur v et renvoie la tête de la liste. Si v est absente, la liste est renvoyée inchangée.
- Quels cas particuliers dois-tu traiter ?
- Écris la fonction.
- Applique-la à avec
v = 7, puis avecv = 3, puis avecv = 5.
Indice 1
La suppression de la tête est un cas à part : il n'y a pas de cellule précédente.
Indice 2
Pour supprimer une cellule au milieu, on fait « sauter » son pointeur : la cellule précédente pointe directement vers la suivante.
Voir la correction pas à pas
Cas particuliers : liste vide, suppression de la tête, valeur absente.
Écriture :
def supprimer(tete, v): if tete is None: return None if tete.valeur == v: return tete.suivant courante = tete while courante.suivant is not None and courante.suivant.valeur != v: courante = courante.suivant if courante.suivant is not None: courante.suivant = courante.suivant.suivant return tetev = 7: la tête vaut 3, ce n'est pas elle qu'on supprime. Dès le départ,courante.suivanta pour valeur 7 : la boucle ne fait aucun tour, et on fait pointercourante(3) vers 9. Résultat : . Seule la première occurrence disparaît.v = 3: la tête est la cellule à supprimer, la fonction renvoietete.suivant. Résultat : .v = 5: la boucle atteint la dernière cellule,courante.suivantvautNone, aucune modification. La liste est inchangée.
On s'arrête sur la cellule qui précède celle à supprimer : une liste simplement chaînée ne permet pas de revenir en arrière. Le test courante.suivant is not None dans la condition de la boucle évite l'erreur sur None.valeur, grâce à l'évaluation paresseuse de and.
Exercice 7 Inverser une liste
Écris une fonction inverser(tete) qui retourne les pointeurs d'une liste simplement chaînée en place, sans créer de nouvelle cellule, et qui renvoie la nouvelle tête.
- Quelles variables auxiliaires te faut-il ?
- Écris la fonction.
- Déroule-la à la main sur .
Indice 1
Il faut mémoriser le suivant avant de modifier le pointeur de la cellule courante.
Indice 2
Au départ, la cellule précédente n'existe pas : elle vaut None, et c'est ce que pointera l'ancienne tête à la fin.
Voir la correction pas à pas
Variables :
precedent(initialisé àNone),courante(initialisée àtete), et une variable temporairesuivantepour ne pas perdre la suite.Écriture :
def inverser(tete): precedent = None courante = tete while courante is not None: suivante = courante.suivant courante.suivant = precedent precedent = courante courante = suivante return precedentTour 1 : la cellule 1 pointe vers
None,precedentdevient la cellule 1,courantepasse sur la cellule 2.Tour 2 : la cellule 2 pointe vers la cellule 1. Tour 3 : la cellule 3 pointe vers la cellule 2.
À la sortie,
courantevautNoneetprecedentdésigne la cellule 3. La liste est , et on renvoieprecedent.
Cette fonction ne crée aucune cellule et ne parcourt la liste qu'une fois. Si tu écris courante.suivant = precedent avant d'avoir sauvegardé suivante, tu perds la suite de la liste : c'est l'erreur la plus fréquente sur cet exercice.
Exercice 8 Accéder à l'élément d'indice k
Dans un tableau, les données sont contiguës en mémoire 3. Dans une liste chaînée, on ne connaît que la tête.
- Écris
acces(tete, k)qui renvoie la valeur de l'élément d'indicek(les indices commencent à 0), ouNonesikdépasse la fin de la liste. - Pour atteindre l'indice 12, combien de fois doit-on suivre un pointeur
suivantà partir de la tête ? - Dans quel cas une liste chaînée est-elle préférable à un tableau ?
Indice 1
L'indice 0 correspond à la tête : aucun déplacement nécessaire.
Indice 2
Pour la question 3, compare la fréquence des accès avec celle des insertions et suppressions 2.
Voir la correction pas à pas
Écriture :
def acces(tete, k): courante = tete i = 0 while courante is not None and i < k: courante = courante.suivant i = i + 1 if courante is None: return None return courante.valeurPour atteindre l'indice 12, il faut partir de l'indice 0 (la tête) et avancer jusqu'à l'indice 12 : 12 déplacements, donc 13 cellules visitées en comptant la tête.
Interprétation : l'accès à l'indice demande déplacements. Dans un tableau, on calcule directement l'emplacement.
Choix de la structure : on recommande souvent une liste chaînée quand l'ordre des éléments compte et que l'on insère ou supprime des éléments n'importe où plus souvent qu'on n'y accède 2. Si l'on accède surtout à des positions arbitraires, un tableau convient mieux.
Une liste chaînée n'offre pas d'accès direct par indice : elle échange cette facilité contre des insertions et des suppressions qui ne déplacent aucune autre cellule. Sa taille n'est limitée que par la mémoire disponible 3.
Exercice 9 Repérer une liste cyclique
Dans une liste cyclique, la fin de la liste ramène sur le premier élément 3. On construit :
a = Cellule(1)
b = Cellule(2)
c = Cellule(3)
a.suivant = b
b.suivant = c
c.suivant = a
- Que se passe-t-il si on appelle
longueur(a)avec la fonction de l'exercice 3 ? - Propose une fonction
est_cyclique(tete)qui renvoieTruesi la liste revient sur une cellule déjà vue. Tu peux utiliser une liste Python pour mémoriser les cellules visitées. - Combien de cellules distinctes la boucle de
est_cyclique(a)visite-t-elle avant de conclure ?
Indice 1
Une cellule déjà vue se repère avec le test courante in vues, qui compare les objets eux-mêmes.
Indice 2
Compte les cellules ajoutées à vues avant que courante ne redevienne une cellule déjà vue.
Voir la correction pas à pas
Avec
longueur(a): la conditioncourante is not Nonene devient jamais fausse, car aucune cellule ne pointe versNone. La boucle ne s'arrête pas.Écriture de
est_cyclique:def est_cyclique(tete): vues = [] courante = tete while courante is not None: if courante in vues: return True vues.append(courante) courante = courante.suivant return FalseDéroulé sur
a: on visitea, puisb, puisc(trois ajouts àvues). Puiscouranteredevienta, déjà dansvues: la fonction renvoieTrue.Le nombre de cellules distinctes visitées est donc 3.
Dans une liste cyclique, il n'y a plus de début ni de fin 3 : tout parcours qui attend None doit être protégé. Cette solution consomme de la mémoire proportionnelle à la longueur de la liste ; elle suffit ici pour le niveau attendu en Terminale.
Les questions qu'on se pose
Pourquoi utiliser une liste chaînée plutôt qu'une liste Python ?
Une liste Python (dite aussi tableau dynamique) se comporte comme un tableau dont la taille s'adapte à l'usage ; en interne, les données d'un tableau sont contiguës en mémoire 3. La liste chaînée, elle, relie des cellules par des pointeurs : on insère ou supprime un élément en modifiant quelques pointeurs, sans déplacer les autres. On la recommande quand l'ordre compte et que les insertions et suppressions sont plus fréquentes que les accès 2. En NSI, on écrit une liste chaînée surtout pour comprendre le fonctionnement des structures de données.
Que faut-il vérifier avant de rendre une fonction sur les listes chaînées ?
Teste les cas particuliers avec des assertions : liste vide, liste à un seul élément, doublons 1. Vérifie aussi que chaque boucle while finit par rencontrer None (sauf dans une liste cyclique), et que tu n'écris jamais courante.suivant.valeur sans avoir contrôlé que courante.suivant n'est pas None.
Comment ne pas se perdre dans les affectations de pointeurs ?
Dessine la liste avant et après l'opération, puis numérote les flèches à modifier. Pose-toi toujours la question : « Si je modifie ce pointeur maintenant, est-ce que je perds l'accès à une partie de la liste ? » Si oui, sauvegarde d'abord la cellule concernée dans une variable. C'est exactement la logique de l'inversion et de l'insertion après une cellule.
Sources
- Ressources IREM - Structures de données NSI, Académie de Lyon. Consulté le 7 novembre 2026.
- Liste chaînée, Wikipédia. Consulté le 7 novembre 2026.
- 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.