Aller au contenu principal

Les listes chaînées

Ce que ce chapitre apporte 5 points
  • Représenter une liste chaînée par deux tableaux parallèles, valeur et suivant.
  • Insérer en tête et supprimer au milieu sans déplacer aucune valeur.
  • Comparer au compteur de pas ce qu'une liste rend immédiat et ce qu'elle rend coûteux.
  • Nommer les parties d'un arbre, construire un arbre binaire de recherche en trois tableaux, puis y chercher une valeur.
  • Expliquer ce que devient un arbre binaire de recherche nourri de valeurs déjà triées.

Une tournée de maintenance qui change d'ordre, un journal d'interventions qui s'allonge par le début, un magasin qui cherche une référence parmi des milliers : chaque fois, la question est de savoir quelle façon de ranger les données rend bon marché l'opération la plus fréquente. Une liste chaînée est une suite de maillons, chacun portant une valeur et l'adresse du suivant. Un tableau range ses valeurs côte à côte, et cette contiguïté décide de tout : lire la n-ième case est immédiat, insérer au début oblige à tout décaler. Chaîner consiste à renoncer au côte à côte et à faire désigner par chaque valeur celle qui la suit. Les deux coûts s'échangent alors, et le compteur de pas le montre sans qu'il faille l'affirmer. Avec deux liens par valeur au lieu d'un, la même idée donne un arbre, où chercher une valeur ne demande plus de tout parcourir, à une condition que la fin du chapitre fait apparaître. Le chapitre s'appuie sur les tableaux, sur les piles, dont il reprend l'empilement, et sur la récursivité, qui parcourt l'arbre.

Ce pseudo-code ne connaît pas d'enregistrement : impossible de fabriquer une case qui contiendrait à la fois une valeur et un lien. La contrainte oblige à écrire les structures chaînées en tableaux parallèles, un tableau par champ, la même position désignant partout le même élément. Loin d'être un pis-aller, c'est la description exacte de ce que fait une machine : la mémoire est un long tableau de cases numérotées, et le parcours d'architecture le montre côté matériel. Ce que le pseudo-code appelle ici une position, la machine l'appelle une adresse, à un détail près : la machine numérote ses cases à partir de 0, le pseudo-code du cours à partir de 1.

Deux tableaux au lieu d'un

Définition

Une liste chaînée est une suite d'éléments dont chacun porte, en plus de sa valeur, la position de son successeur. Une position convenue, ici 0, qu'aucune case ne porte puisque les tableaux commencent à 1, marque la fin de la chaîne. Une variable retient la position du premier élément : c'est la tête, et sans elle la liste est perdue.

Le tableau valeur contient les données, le tableau suivant contient les liens, et rien n'impose que l'ordre des cases soit l'ordre de la chaîne : c'est même tout l'intérêt. Une tournée de maintenance visite quatre capteurs. Leurs fiches sont rangées dans l'ordre d'installation, C1 en case 1 jusqu'à C4 en case 4, mais la tournée les visite dans un autre ordre : C2, C4, C1, puis C3. Le tableau suivant enregistre cet ordre sans déplacer une seule fiche. La tête vaut 2 ; la case 2 renvoie à la case 4, la case 4 à la case 1, la case 1 à la case 3, et la case 3, dernière de la tournée, porte 0.

Position1234
valeurC1C2C3C4
suivant3401
Graphe orienté5 sommets, 4 arcs
têteC2C4C1C3
têteC2C4C1C3
La tournée dans l'ordre des liens. Les fiches restent rangées de C1 à C4 dans l'ordre des cases ; seul le tableau des liens décide de l'ordre de visite, et C3, dernière de la tournée, ne mène plus nulle part.

Parcourir ne consiste plus à compter de 1 à n, mais à suivre les liens depuis la tête jusqu'au 0 final.

Algorithme
pas 1 / 17
Début
valeur ← ["C1", "C2", "C3", "C4"]
suivant ← [3, 4, 0, 1]
tete ← 2
c ← tete
TantQue c <> 0
Écrire "case ", c, " : capteur ", valeur[c], ", renvoie à ", suivant[c]
c ← suivant[c]
FinTantQue
Fin

programme principal

valeur["C1", "C2", "C3", "C4"]

17 pas, et c prend les valeurs 2, 4, 1, 3 puis 0 : elle saute d'une case à l'autre au lieu d'avancer d'un cran. La variable c n'est donc pas un compteur : c'est une position courante, et elle ne progresse que parce que la case où elle se trouve lui dit où aller. C'est la différence de fond avec le parcours d'un tableau, où l'indice avance tout seul. Changer l'ordre de la tournée reviendrait à réécrire quelques liens, sans déplacer aucune fiche.

Le test porte sur la position courante, pas sur la suivante

L'erreur classique consiste à écrire TantQue suivant[c] <> 0 au lieu de TantQue c <> 0. La boucle s'arrête alors avant d'avoir traité le dernier élément, qui est justement celui dont le lien vaut 0 : la tournée oublierait C3. Sur une liste vide, où la tête vaut 0, le test fautif réclame même suivant[0], et l'algorithme s'arrête sur une case qui n'existe pas. Le test porte sur la position où l'on se trouve, jamais sur celle où l'on va.

Vérification rapideon peut se reprendre

Dans une liste chaînée en deux tableaux, à quoi sert la valeur 0 dans suivant ?

Insérer en tête : le décalage contre trois affectations

Voici la comparaison qui justifie la structure. Huit valeurs, une neuvième à placer en première position.

Sur un tableau, toutes les valeurs doivent reculer d'une case, en partant de la fin pour ne rien écraser :

Algorithme
pas 1 / 22
Début
t ← [10, 20, 30, 40, 50, 60, 70, 80, 0]
n ← 8
Pour i de n à 1 pas -1
t[i + 1] ← t[i]
FinPour
t[1] ← 5
n ← n + 1
Écrire t
Fin

programme principal

t[10, 20, 30, 40, 50, 60, 70, 80, 0]

22 pas, dont 17 passés dans la seule boucle de décalage. Doubler le nombre de valeurs doublerait ce coût. La neuvième case est réservée d'avance, et son 0 n'est qu'un remplissage : un tableau créé avec ses valeurs garde son nombre de cases, et il faut donc prévoir celle que le décalage va occuper.

Sur une liste, rien ne bouge. La nouvelle valeur se pose dans une case libre, son lien désigne l'ancienne tête, et la tête change de valeur :

Algorithme
pas 1 / 8
Début
valeur ← [10, 20, 30, 40, 50, 60, 70, 80, 0]
suivant ← [2, 3, 4, 5, 6, 7, 8, 0, 0]
tete ← 1
libre ← 9
valeur[libre] ← 5
suivant[libre] ← tete
tete ← libre
Écrire "tête : ", valeur[tete], " puis ", valeur[suivant[tete]]
Fin

programme principal

valeur[10, 20, 30, 40, 50, 60, 70, 80, 0]

8 pas, dont trois pour l'insertion proprement dite. Le nombre d'éléments déjà présents n'y change rien : ce serait trois affectations sur huit valeurs comme sur huit mille. La case 9 est la case libre, préparée d'avance comme celle du tableau ; tant qu'aucun lien n'y mène, ce qu'elle contient n'appartient pas à la chaîne. La tête joue ici le rôle du sommet de la pile du chapitre précédent : la dernière valeur insérée est la première que rencontre le parcours, et insérer en tête revient à empiler, sans rien décaler.

L'ordre des deux affectations n'est pas libre

Inverser suivant[libre] ← tete et tete ← libre perd la liste entière. La tête désigne déjà la nouvelle case quand son lien est écrit : suivant[9] reçoit 9, la case renvoie à elle-même, et les huit valeurs d'origine ne sont plus sur le chemin de personne. Un parcours affiche alors 5 sans fin, jusqu'au plafond des cinq cents pas. La règle vaut pour toute modification d'une chaîne, comme pour les deux lignes qui empilent : accrocher le nouveau maillon à ce qui existe avant de déplacer la tête, jamais après.

La liste vide n'est pas un cas particulier : tete vaut 0, le parcours ne fait aucun tour, et l'insertion en tête y fonctionne telle quelle, puisque le nouveau maillon reçoit 0 comme lien, c'est-à-dire la marque de fin.

La suppression obéit à la même logique. Retirer le troisième élément d'une chaîne ne demande pas de reboucher un trou, mais de faire pointer son prédécesseur par-dessus lui :

Algorithme
pas 1 / 17
Début
valeur ← [10, 20, 30, 40]
suivant ← [2, 3, 4, 0]
tete ← 1
p ← 2 // le prédécesseur de la case à retirer
retire ← suivant[p] // la case qui quitte la chaîne
suivant[p] ← suivant[retire] // le prédécesseur saute par-dessus
c ← tete
TantQue c <> 0
Écrire valeur[c]
c ← suivant[c]
FinTantQue
Fin

programme principal

valeur[10, 20, 30, 40]

17 pas, et la sortie donne 10, 20, 40. La ligne décisive se lit de droite à gauche : le prédécesseur reçoit le successeur de la case retirée, et la chaîne passe par-dessus elle. La valeur 30 est toujours dans le tableau valeur, intacte ; elle a simplement cessé d'appartenir à la chaîne. Une case qui n'est sur le chemin de personne n'existe plus, du point de vue de la liste, et la case 3 ainsi libérée pourra accueillir la prochaine insertion.

Cette affectation unique suppose cependant que p soit connu, et le trouver demande de parcourir la chaîne depuis la tête, comme pour lire la n-ième valeur, que la section suivante mesure : supprimer au milieu ne déplace aucune valeur, mais ne coûte une seule affectation qu'une fois arrivé au bon endroit. Retirer la tête, qui n'a pas de prédécesseur, est le seul cas à part, et tete ← suivant[tete] y suffit.

Vérification rapideon peut se reprendre

Insérer une valeur en tête coûte 22 pas sur un tableau de huit valeurs et 8 pas sur une liste. Pourquoi ?

Lire la n-ième valeur : les rôles s'inversent

L'avantage se paie, et il se paie sur l'accès direct. Dans un tableau, la sixième valeur est à l'indice 6, sans discussion :

Algorithme
pas 1 / 2
Début
t ← [10, 20, 30, 40, 50, 60, 70, 80]
Écrire "sixième valeur : ", t[6]
Fin

programme principal

t[10, 20, 30, 40, 50, 60, 70, 80]

2 pas. Dans une liste, la sixième valeur n'est nulle part en particulier : il faut partir de la tête et suivre cinq liens.

Algorithme
pas 1 / 16
Début
valeur ← [10, 20, 30, 40, 50, 60, 70, 80]
suivant ← [2, 3, 4, 5, 6, 7, 8, 0]
tete ← 1
c ← tete
Pour k de 1 à 5
c ← suivant[c]
FinPour
Écrire "sixième valeur : ", valeur[c]
Fin

programme principal

valeur[10, 20, 30, 40, 50, 60, 70, 80]

16 pas pour le même résultat, et ce coût grandit avec le rang demandé, tandis que celui du tableau ne bouge jamais.

Opération sur huit valeursTableauListe chaînée
Insérer en tête22 pas8 pas
Lire la sixième valeur2 pas16 pas

Les deux structures échangent leurs forces. Aucune des deux structures n'est meilleure. Elles échangent leurs forces : ce que la contiguïté offre à la lecture, elle le reprend à l'insertion, et le chaînage fait l'inverse. Le choix se décide sur l'opération la plus fréquente dans l'usage visé, et non sur une préférence.

Vérification rapideon peut se reprendre

Lire la sixième valeur coûte 2 pas sur un tableau et 16 sur une liste chaînée. Qu'est-ce que cela illustre ?

L'arbre binaire de recherche

Chaîner ne se limite pas à mettre des éléments à la suite. Avec deux liens par élément au lieu d'un, la chaîne devient un arbre.

Un arbre se décrit avec quelques mots. Chaque élément est un nœud, et le nœud d'où tout part est la racine. Les deux nœuds qu'un nœud désigne par ses liens sont ses fils, gauche et droit ; tout ce qui descend d'un fils forme un sous-arbre, et un nœud sans fils est une feuille. La hauteur compte les étages, de la racine à la feuille la plus basse, et un arbre est équilibré quand ses branches ont à peu près la même hauteur, ce qui garde courte la descente depuis la racine.

Définition

Un arbre binaire de recherche est un arbre où chaque nœud porte une valeur, un lien vers un sous-arbre gauche et un lien vers un sous-arbre droit, avec cette règle : tout ce qui est à gauche d'un nœud lui est inférieur, tout ce qui est à droite lui est supérieur ou égal. La règle vaut pour chaque nœud, pas seulement pour la racine.

Un entrepôt enregistre les références de ses articles au fil des arrivées : 8, 3, 10, 1, 6, puis 14. Rangées dans un arbre binaire de recherche, elles forment l'arbre suivant.

Graphe orienté et pondéré6 sommets, 5 arcschemin mis en évidence
gauchedroitegauchedroitedroite83101614
gauchedroitegauchedroitedroite83101614
Les six références rangées dans leur ordre d'arrivée, racine à gauche. Chaque flèche est un lien, marqué gauche ou droite ; en couleur, le chemin qui mène de la racine à la référence 14.

La racine porte 8. Ses fils sont 3 et 10, et 1, 6 et 14 sont des feuilles. Le sous-arbre gauche de la racine contient 3, 1 et 6, toutes inférieures à 8 ; son sous-arbre droit contient 10 et 14, qui ne le sont pas. L'arbre compte trois étages, et il est équilibré : aucune branche n'y est beaucoup plus longue qu'une autre.

Trois tableaux parallèles suffisent à l'écrire : valeur, gauche et droite, avec toujours 0 pour l'absence de lien. Chaque référence occupe la case de son rang d'arrivée.

Position123456
valeur83101614
gauche240000
droite356000

La racine est en position 1, elle porte 8, son fils gauche est en position 2 (la valeur 3) et son fils droit en position 3 (la valeur 10). Chaque nœud est rangé là où il y avait de la place, et la forme de l'arbre n'est inscrite nulle part ailleurs que dans les liens.

Ces tableaux se construisent au fil des arrivées. L'insertion descend depuis la racine en comparant, et accroche le nouveau nœud au premier lien vide rencontré. Voici l'insertion de 6, cinquième valeur arrivée, rangée en case 5. La descente part de la racine, en case 1, qui porte 8. Comme 6 est plus petit, elle regarde à gauche : gauche[1] vaut 2, ce lien n'est pas vide, et la descente passe en case 2, qui porte 3. Comme 6 n'est pas plus petit que 3, elle regarde à droite : droite[2] vaut 0, la place est libre, et droite[2] reçoit 5.

L'algorithme suivant répète cette descente pour chacune des six valeurs. La variable c est la case où se trouve la descente, et place passe à Vrai quand le nouveau nœud est accroché, ce qui arrête le TantQue. La toute première valeur n'a rien à chercher, puisqu'elle devient la racine : c'est le rôle du test Si n > 1.

Algorithme
pas 1 / 104
Début
entrantes ← [8, 3, 10, 1, 6, 14]
valeur ← tableau[6]
gauche ← tableau[6]
droite ← tableau[6]
n ← 0
Pour k de 1 à 6
n ← n + 1
valeur[n] ← entrantes[k]
gauche[n] ← 0
droite[n] ← 0
Si n > 1 Alors
c ← 1
place ← Faux
TantQue NON place
Si valeur[n] < valeur[c] Alors
Si gauche[c] = 0 Alors
gauche[c] ← n
place ← Vrai
Sinon
c ← gauche[c]
FinSi
Sinon
Si droite[c] = 0 Alors
droite[c] ← n
place ← Vrai
Sinon
c ← droite[c]
FinSi
FinSi
FinTantQue
FinSi
FinPour
Écrire "valeur : ", valeur
Écrire "gauche : ", gauche
Écrire "droite : ", droite
Fin

programme principal

entrantes[8, 3, 10, 1, 6, 14]

104 pas, et les trois tableaux en sortie sont exactement ceux du tableau précédent.

Chercher revient alors à descendre : à chaque nœud, une seule comparaison élimine tout un sous-arbre. Pour savoir si la référence 14 est enregistrée, la descente suit le chemin coloré de la figure de l'arbre.

Algorithme
pas 1 / 19
séparées par des virgules, décimales au point
Début
valeur ← [8, 3, 10, 1, 6, 14]
gauche ← [2, 4, 0, 0, 0, 0]
droite ← [3, 5, 6, 0, 0, 0]
Lire cible
c ← 1
TantQue c <> 0 ET valeur[c] <> cible
Si cible < valeur[c] Alors
Écrire cible, " est plus petite que ", valeur[c], " : à gauche"
c ← gauche[c]
Sinon
Écrire cible, " est plus grande que ", valeur[c], " : à droite"
c ← droite[c]
FinSi
FinTantQue
Si c = 0 Alors
Écrire "valeur absente de l'arbre"
Sinon
Écrire "trouvée en case ", c
FinSi
Fin

programme principal

valeur[8, 3, 10, 1, 6, 14]
À manipuler
Saisir tour à tour dans le champ « Ce que Lire reçoit » les six références de l'arbre, 8, 3, 10, 1, 6 et 14, et dérouler chaque fois jusqu'au bout. Compter les lignes « à gauche » ou « à droite » que la sortie affiche avant le verdict : aucune pour 8, une pour 3 et pour 10, deux pour 1, 6 et 14. Saisir ensuite 20, plus grande que toutes : trois lignes, puis « valeur absente de l'arbre ». Constater que le nombre de lignes ne dépasse jamais le nombre d'étages de l'arbre, trois : chaque ligne fait descendre d'un étage, et c'est la hauteur, non le nombre de références, qui borne le travail.

19 pas et deux descentes seulement pour atteindre 14, au fond de l'arbre. Le champ de saisie de la figure accepte une autre cible : avec 7, absente de l'arbre, la descente passe par 8, 3 et 6, tombe sur un lien nul, et l'algorithme le dit en 22 pas. Ce cas n'est possible que parce que la condition teste c <> 0 avant valeur[c] : ET n'examine sa partie droite que si sa partie gauche est vraie, et la règle posée au chapitre sur les tris s'applique telle quelle. Dans l'autre ordre, la figure réclamerait valeur[0], qui n'existe pas.

Parcourir un arbre dans l'ordre

La règle de placement a une conséquence remarquable : visiter d'abord tout le sous-arbre gauche, puis le nœud, puis tout le sous-arbre droit rend les valeurs triées. C'est le parcours infixe, et il s'écrit naturellement par récursion, chaque sous-arbre se traitant comme un arbre.

Algorithme
pas 1 / 48
Fonction Infixe(valeur, gauche, droite, c)
Si c <> 0 Alors
Infixe(valeur, gauche, droite, gauche[c])
Écrire valeur[c]
Infixe(valeur, gauche, droite, droite[c])
FinSi
FinFonction
Début
valeur ← [8, 3, 10, 1, 6, 14]
gauche ← [2, 4, 0, 0, 0, 0]
droite ← [3, 5, 6, 0, 0, 0]
Infixe(valeur, gauche, droite, 1)
Fin

programme principal

valeur[8, 3, 10, 1, 6, 14]

48 pas, et la sortie est 1, 3, 6, 8, 10, 14. La pile des appels affichée par la figure mérite d'être suivie : elle monte jusqu'à cinq cadres, et le nœud n'est écrit qu'au retour du premier appel, jamais avant. Le cas de base est ici un lien nul, qui ne fait rien du tout : c'est la forme la plus économique de cas de base, celle qui n'a pas besoin d'être traitée à part.

Vérification rapideon peut se reprendre

Que produit le parcours infixe d'un arbre binaire de recherche ?

Ce qui arrive aux valeurs déjà triées

L'arbre précédent a coûté 104 pas à construire, et deux descentes pour trouver 14. Voici le même algorithme, mot pour mot, nourri des mêmes six références arrivées cette fois dans l'ordre croissant, comme les livrerait un fichier déjà trié.

Algorithme
pas 1 / 150
Début
entrantes ← [1, 3, 6, 8, 10, 14]
valeur ← tableau[6]
gauche ← tableau[6]
droite ← tableau[6]
n ← 0
Pour k de 1 à 6
n ← n + 1
valeur[n] ← entrantes[k]
gauche[n] ← 0
droite[n] ← 0
Si n > 1 Alors
c ← 1
place ← Faux
TantQue NON place
Si valeur[n] < valeur[c] Alors
Si gauche[c] = 0 Alors
gauche[c] ← n
place ← Vrai
Sinon
c ← gauche[c]
FinSi
Sinon
Si droite[c] = 0 Alors
droite[c] ← n
place ← Vrai
Sinon
c ← droite[c]
FinSi
FinSi
FinTantQue
FinSi
FinPour
Écrire "valeur : ", valeur
Écrire "gauche : ", gauche
Écrire "droite : ", droite
Fin

programme principal

entrantes[1, 3, 6, 8, 10, 14]

150 pas au lieu de 104, et surtout un tableau gauche entièrement nul : [0, 0, 0, 0, 0, 0]. Chaque valeur, plus grande que toutes les précédentes, s'est accrochée à droite de la dernière. L'arbre n'a plus aucune branche gauche : c'est un peigne, et un peigne n'est rien d'autre qu'une liste chaînée déguisée en arbre. Sa hauteur est de six étages, contre trois pour l'arbre équilibré des mêmes valeurs.

Graphe orienté et pondéré6 sommets, 5 arcschemin mis en évidence
droitedroitedroitedroitedroite13681014
droitedroitedroitedroitedroite13681014
Les mêmes six références, arrivées dans l'ordre croissant. Plus aucun lien à gauche : le chemin de la racine à 14 passe par toutes les valeurs, en cinq descentes au lieu de deux.
Algorithme
pas 1 / 34
séparées par des virgules, décimales au point
Début
valeur ← [1, 3, 6, 8, 10, 14]
gauche ← [0, 0, 0, 0, 0, 0]
droite ← [2, 3, 4, 5, 6, 0]
Lire cible
c ← 1
TantQue c <> 0 ET valeur[c] <> cible
Si cible < valeur[c] Alors
Écrire cible, " est plus petite que ", valeur[c], " : à gauche"
c ← gauche[c]
Sinon
Écrire cible, " est plus grande que ", valeur[c], " : à droite"
c ← droite[c]
FinSi
FinTantQue
Si c = 0 Alors
Écrire "valeur absente de l'arbre"
Sinon
Écrire "trouvée en case ", c
FinSi
Fin

programme principal

valeur[1, 3, 6, 8, 10, 14]

34 pas et cinq descentes, contre 19 pas et deux descentes sur l'arbre équilibré, pour chercher la même valeur dans les mêmes six données. Aucune comparaison n'élimine plus rien : la recherche parcourt tout, exactement comme dans une liste.

L'ordre d'arrivée des données suffit à ruiner l'arbre

L'arbre binaire de recherche n'est donc rapide que tant qu'il reste équilibré, et l'ordre d'arrivée des données suffit à le ruiner. Le cas fatal, insérer des valeurs déjà triées, est aussi le plus probable en pratique : les données arrivent souvent d'un fichier ou d'une base qui les a déjà rangées. Des arbres qui se rééquilibrent seuls à chaque insertion existent pour cette raison ; leur mécanique dépasse ce parcours, mais le problème qu'ils résolvent est exactement celui qui vient d'être mesuré.

Vérification rapideon peut se reprendre

Un arbre binaire de recherche reçoit des valeurs déjà triées. Que devient-il ?

Mettre en pratique

Un lien suivi, une valeur décalée, un étage descendu : chacun de ces coûts se compte à partir des données, sans dérouler aucune figure.

Des liens, des décalages et des étages

  • 1.

    Une liste chaînée tient 500 interventions. Combien de liens faut-il suivre depuis la tête pour atteindre la 120e ?

  • 2.

    Un tableau contient 20 relevés. Cinq nouveaux relevés y sont insérés en tête, l'un après l'autre. Combien de valeurs sont décalées en tout ?

  • 3.

    Un arbre binaire de recherche a quatre étages, et chaque nœud des trois premiers a ses deux fils. Combien de références contient-il ?

  • 4.

    Combien d'étages faut-il au minimum pour ranger 1000 références dans un arbre binaire de recherche ?

  • 5.

    Les mêmes 1000 références arrivent triées, dans l'ordre croissant. Combien de descentes faut-il pour atteindre la plus grande ?

Les deux dernières questions portent sur les mêmes références : seul leur ordre d'arrivée sépare les deux réponses.

Exercice 1, La longueur d'une tournée

Une tournée d'inspection de vannes est rangée en deux tableaux parallèles, et sa tête vaut 5. Les cases 2 et 3 portent deux vannes retirées de la tournée : elles forment encore entre elles une petite chaîne, de la case 3 à la case 2, mais aucun lien parti de la tête n'y mène. Écrire un algorithme qui compte les vannes réellement visitées.

Position123456
valeurV1V2V3V4V5V6
suivant602140
Afficher la solution

La longueur d'une liste chaînée n'est écrite nulle part : elle se compte, en suivant les liens depuis la tête jusqu'au 0 final, avec un compteur qui augmente de 1 à chaque maillon.

Algorithme
pas 1 / 19
Début
valeur ← ["V1", "V2", "V3", "V4", "V5", "V6"]
suivant ← [6, 0, 2, 1, 4, 0]
tete ← 5
compte ← 0
c ← tete
TantQue c <> 0
compte ← compte + 1
c ← suivant[c]
FinTantQue
Écrire compte, " vannes dans la tournée"
Fin

programme principal

valeur["V1", "V2", "V3", "V4", "V5", "V6"]

La figure affiche 4 : la position courante passe par les cases 5, 4, 1 et 6, puis vaut 0. Les six cases du tableau ne disent rien de la longueur de la chaîne, puisque les cases 3 et 2 ne sont sur le chemin de personne. Ce comptage parcourt toute la liste, et son coût grandit avec elle, comme celui de la lecture de la n-ième valeur : une liste dont la longueur sert souvent la tient plutôt à jour dans une variable, augmentée à chaque insertion. Sur une liste vide, où la tête vaut 0, la boucle ne fait aucun tour et l'algorithme affiche 0, sans cas particulier.

Dans la même tournée, la vanne V1, en case 1, est déposée pour réparation. Écrire l'algorithme qui la retire de la chaîne sans connaître d'avance la position de son prédécesseur, puis affiche la tournée restante.

Retirer une case demande de faire pointer son prédécesseur par-dessus elle, et ce prédécesseur se cherche depuis la tête : c'est la case dont le lien désigne la case à retirer. La tête, qui n'a pas de prédécesseur, est le seul cas à part.

Algorithme
pas 1 / 22
Début
valeur ← ["V1", "V2", "V3", "V4", "V5", "V6"]
suivant ← [6, 0, 2, 1, 4, 0]
tete ← 5
retire ← 1 // la case de V1
Si tete = retire Alors
tete ← suivant[tete]
Sinon
p ← tete
TantQue suivant[p] <> retire
p ← suivant[p]
FinTantQue
suivant[p] ← suivant[retire]
FinSi
c ← tete
TantQue c <> 0
Écrire valeur[c]
c ← suivant[c]
FinTantQue
Fin

programme principal

valeur["V1", "V2", "V3", "V4", "V5", "V6"]

La recherche s'arrête en case 4, celle de V4, dont le lien désignait V1 ; suivant[4] reçoit alors le lien de V1, la case 6, et la tournée affiche V5, V4 puis V6. Le test porte cette fois sur la case suivante, suivant[p] <> retire, et c'est voulu : la boucle cherche la case qui désigne V1, et doit donc s'arrêter un maillon avant elle. Ce test suppose que la vanne figure bien dans la tournée. Sinon p finirait par valoir 0, et l'algorithme réclamerait suivant[0], qui n'existe pas : c'est la faute que signale l'encadré « Le test porte sur la position courante, pas sur la suivante », et elle se prévient de la même façon, en vérifiant la position avant de lire son lien.

Un magasin de pièces détachées enregistre sept références, numérotées de 1 à 7. Dans quel ordre les insérer pour que l'arbre binaire de recherche n'ait que trois étages ? Vérifier la réponse avec l'algorithme d'insertion du chapitre, puis donner le nombre de descentes que demande, au pire, la recherche d'une référence enregistrée.

La racine doit partager les références en deux moitiés égales : c'est la médiane, 4, qui arrive la première. Chacune des deux moitiés, de 1 à 3 et de 5 à 7, se range ensuite de la même façon sous sa propre médiane, 2 et 6. Les quatre références restantes, 1, 3, 5 et 7, viennent en dernier, dans n'importe quel ordre : chacune tombe sur un lien vide du troisième étage.

Algorithme
pas 1 / 124
Début
entrantes ← [4, 2, 6, 1, 3, 5, 7]
valeur ← tableau[7]
gauche ← tableau[7]
droite ← tableau[7]
n ← 0
Pour k de 1 à 7
n ← n + 1
valeur[n] ← entrantes[k]
gauche[n] ← 0
droite[n] ← 0
Si n > 1 Alors
c ← 1
place ← Faux
TantQue NON place
Si valeur[n] < valeur[c] Alors
Si gauche[c] = 0 Alors
gauche[c] ← n
place ← Vrai
Sinon
c ← gauche[c]
FinSi
Sinon
Si droite[c] = 0 Alors
droite[c] ← n
place ← Vrai
Sinon
c ← droite[c]
FinSi
FinSi
FinTantQue
FinSi
FinPour
Écrire "valeur : ", valeur
Écrire "gauche : ", gauche
Écrire "droite : ", droite
Fin

programme principal

entrantes[4, 2, 6, 1, 3, 5, 7]

La sortie donne gauche à [2, 4, 6, 0, 0, 0, 0] et droite à [3, 5, 7, 0, 0, 0, 0] : la racine 4 a pour fils 2 et 6, qui ont chacun deux fils, et les quatre dernières cases sont des feuilles. L'arbre a trois étages, et la recherche d'une référence enregistrée demande au pire deux descentes, celles qui mènent à une feuille. Les mêmes références arrivées dans l'ordre croissant donneraient un peigne de sept étages, où atteindre 7 demanderait six descentes. Sept est d'ailleurs le plus grand nombre de références que trois étages peuvent tenir : un nœud au premier, deux au deuxième, quatre au troisième.

Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?

Dans la bibliothèque d'exercices