C2 — Boucles et tableauxDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Licence 1 · Algorithmique 1

Cours 2Boucles et tableaux

Répéter un traitement, puis l'appliquer à une structure de données sans déborder.

2 chapitres · 50 min de travail estimé

  1. 1. Boucles25 min
  2. 2. Tableaux et parcours25 min

Chapitre 1 · 25 min

Boucles

Choisir entre Pour et Tant que, maîtriser le compteur et l'accumulateur.

Écrire cent fois la même ligne n'est pas une option. La boucle est la construction qui permet à quinze lignes d'algorithme de traiter un million de données — et c'est précisément ce qui rend une machine utile.

Tant que : répéter jusqu'à ce que la condition tombe

TantQue condition Faire    ...instructions...FinTantQue

Le mécanisme tient en trois temps, et l'ordre compte. On évalue la condition. Si elle est VRAIE, on exécute le corps, puis on revient au test. Si elle est FAUSSE, on saute directement après le FinTantQue.

Conséquence importante : le test a lieu avant le corps. Si la condition est fausse dès le départ, le corps n'est jamais exécuté. Zéro tour est un résultat parfaitement normal, et souvent le comportement correct — une boucle qui traite les éléments d'une liste vide ne doit rien faire.

Compteur et accumulateur

Presque toute boucle utile met en scène deux rôles distincts, qu'il faut apprendre à distinguer.

Le compteur sait où on en est : i ← i + 1 à chaque tour. Il ne dépend pas du contenu traité, seulement du nombre de tours effectués.

L'accumulateur garde la mémoire de ce qui a été traité : somme ← somme + i. Sa valeur finale est le résultat de l'algorithme.

Les deux doivent être initialisés avant la boucle. Et cette initialisation n'est pas arbitraire : un accumulateur de somme part de 0, l'élément neutre de l'addition ; un accumulateur de produit part de 1. Partir de 0 pour un produit donnerait invariablement 0.

Animation · 16 étapes

Somme des entiers de 1 à 4 avec une boucle Tant que

  1. Le compteur démarre à 1i compte les tours. Il doit exister AVANT la boucle : une variable créée dans le corps repartirait de zéro à chaque tour.
  2. L'accumulateur démarre à 00 est l'élément neutre de l'addition : il ne fausse pas le total. Pour un produit, on initialiserait à 1.
  3. Tour 1 — test : 1 ≤ 4 ? VRAILe test a lieu AVANT le corps. S'il était faux dès le départ, le corps ne serait jamais exécuté — zéro tour est un résultat parfaitement valide.
  4. Tour 1 — on accumule : 0 + 1 = 1somme ← somme + i : on relit somme, on ajoute i, on range le tout dans somme.
  5. Tour 1 — on avance : i passe à 2La ligne la plus oubliée du cours. Sans elle, i resterait à 1, le test resterait vrai, et la boucle tournerait indéfiniment.
  6. Tour 2 — test : 2 ≤ 4 ? VRAIRetour en haut de la boucle. Le test est réévalué avec les valeurs actuelles.
  7. Tour 2 — on accumule : 1 + 2 = 3L'accumulateur garde la mémoire des tours précédents.
  8. Tour 2 — on avance : i passe à 3Le compteur, lui, ne dépend pas du contenu traité.
  9. Tour 3 — test : 3 ≤ 4 ? VRAIMême schéma : test, corps, avancement.
  10. Tour 3 — on accumule : 3 + 3 = 6Les deux 3 n'ont rien à voir : l'un est somme, l'autre est i.
  11. Tour 3 — on avance : i passe à 4Encore un tour possible.
  12. Tour 4 — test : 4 ≤ 4 ? VRAIL'égalité passe, car ≤ inclut 4. Avec < on ferait un tour de moins et la somme vaudrait 6 : c'est l'erreur « à un près » la plus courante.
  13. Tour 4 — on accumule : 6 + 4 = 10Dernier ajout.
  14. Tour 4 — on avance : i passe à 5C'est cet avancement qui va faire échouer le test et arrêter la boucle.
  15. Test : 5 ≤ 4 ? FAUX — on sortLe corps n'est pas exécuté cette fois. On saute au FinTantQue. Notez que i vaut 5 après la boucle, pas 4.
  16. On affiche le total1 + 2 + 3 + 4 = 10. Quatre tours pour quatre valeurs.

Cliquez l'étape 5, puis l'étape 15. Entre les deux, le même bloc de trois lignes a été parcouru quatre fois — c'est exactement ce que « boucle » veut dire. Et remarquez l'étape 15 : i vaut 5 à la sortie, pas 4. Le compteur dépasse toujours d'un cran la dernière valeur traitée, puisque c'est ce dépassement qui fait échouer le test et arrête la boucle.

Quiz · 1 question

Dans la trace, pourquoi la boucle s'arrête-t-elle après le quatrième tour ?

  • Parce que somme a atteint 10
  • Parce que i vaut 5 et que le test 5 ≤ 4 est FAUX
  • Parce qu'une boucle Tant que fait toujours quatre tours

Réponse : Seule la condition décide. C'est l'incrément de i qui finit par la rendre fausse : la boucle s'arrête parce qu'elle a été construite pour progresser vers son propre arrêt.

La boucle infinie

Retirez la ligne i ← i + 1 de la trace précédente. i reste à 1, le test 1 ≤ 4 reste vrai, et la boucle tourne pour toujours. C'est l'erreur la plus courante du semestre, et elle viole la première exigence de la leçon 1 : la finitude.

La règle de relecture est simple : le corps de la boucle doit contenir quelque chose qui fait progresser la condition vers FAUX. Si vous ne trouvez pas cette instruction, la boucle ne s'arrêtera pas.

Quiz · 1 question

Que fait cet algorithme : i ← 10 ; TantQue i > 0 Faire ; Écrire(i) ; i ← i + 1 ; FinTantQue ?

  • Il affiche 10, 9, 8… jusqu'à 1
  • Il n'affiche rien
  • Il affiche 10, 11, 12… indéfiniment

Réponse : L'incrément va dans le mauvais sens : i s'éloigne de la condition d'arrêt au lieu de s'en rapprocher. Il fallait i ← i − 1. Une boucle infinie n'est pas forcément une boucle sans incrément.

Pour : quand le nombre de tours est connu d'avance

Pour i de 1 à 4 Faire    somme ← somme + iFinPour

Cette boucle fait exactement la même chose que la trace ci-dessus, en trois lignes au lieu de sept. Le Pour regroupe au même endroit l'initialisation du compteur, le test et l'incrément — ce qui rend l'oubli de l'incrément impossible. C'est sa vraie qualité, bien plus que la concision.

Les bornes sont incluses des deux côtés : Pour i de 1 à 4 fait quatre tours, avec i valant successivement 1, 2, 3 puis 4.

Le choix entre les deux se fait sur une seule question : sait-on compter les tours avant d'entrer dans la boucle ?

SituationBoucle
Parcourir les 20 cases d'un tableauPour
Répéter 10 fois une opérationPour
Lire des données jusqu'au mot « fin »TantQue
Redemander une saisie tant qu'elle est invalideTantQue

Tout Pour peut se réécrire en TantQue ; l'inverse est faux. Un Pour est un TantQue discipliné.

Quiz · 1 question

Combien de tours fait Pour i de 0 à 9 Faire … FinPour ?

  • 9bornes exclues
  • 10bornes incluses
  • 11une borne comptée deux fois

Réponse : Les deux bornes sont incluses : i prend les valeurs 0, 1, …, 9, soit dix valeurs. La formule générale est fin − début + 1. Compter les tours d'une boucle est la première étape de la leçon 8.

Cette somme des entiers de 1 à nn a d'ailleurs une formule fermée, connue depuis l'Antiquité :

1+2++n=n(n+1)21 + 2 + \dots + n = \frac{n(n+1)}{2}

Elle donne le même résultat que la boucle, mais en une seule opération au lieu de nn. Gardez-la en tête : nous la retrouverons à la leçon 8, quand il s'agira de compter le travail d'un algorithme de tri.

À vous

Exercice de code

Écrivez la somme de 1 à n des deux façons, puis vérifiez qu'elles donnent le même résultat.

Point de départ

// 1. Corrigez la boucle Tant que pour qu'elle somme les entiers de 1 à n.
// 2. Écrivez ensuite la même chose avec une boucle Pour.
function sommeTantQue(n) {
  let i = 1;
  let somme = 0;
  while (i <= 0) {   // ← condition à corriger
    // à compléter : accumuler, PUIS avancer le compteur
  }
  return somme;
}

function sommePour(n) {
  let somme = 0;
  // à compléter
  return somme;
}

console.log(sommeTantQue(4), sommePour(4));      // attendu : 10 10
console.log(sommeTantQue(100), sommePour(100));  // attendu : 5050 5050

Solution

function sommeTantQue(n) {
  let i = 1;
  let somme = 0;
  while (i <= n) {
    somme = somme + i;
    i = i + 1;       // sans cette ligne : boucle infinie
  }
  return somme;
}

// Quand le nombre de tours est connu d'avance, la boucle Pour dit la même
// chose en une ligne : déclaration, condition et avancement au même endroit,
// donc impossible d'oublier l'incrément.
function sommePour(n) {
  let somme = 0;
  for (let i = 1; i <= n; i++) {
    somme = somme + i;
  }
  return somme;
}

console.log(sommeTantQue(4), sommePour(4));
console.log(sommeTantQue(100), sommePour(100));

À retenir

Flashcards · 2 cartes

Quelle question décide entre Pour et Tant que ?
Sait-on compter les tours AVANT d'entrer dans la boucle ? Oui : Pour. Non : Tant que.
Comment initialiser un accumulateur ?
Avec l'élément neutre de l'opération : 0 pour une somme, 1 pour un produit. Et toujours AVANT la boucle.

Chapitre 2 · 25 min

Tableaux et parcours

Manipuler les indices sans déborder : somme, moyenne, minimum, maximum.

Vingt notes à traiter ne justifient pas vingt variables. Le tableau est la structure qui regroupe plusieurs valeurs de même type sous un seul nom, chacune repérée par un numéro.

Variables    T : tableau de 5 entiersDébut    T[0] ← 12    T[1] ← 5    ...

Deux propriétés à retenir. Toutes les cases ont le même type : un tableau d'entiers ne contient que des entiers. Et l'accès à une case est immédiat : atteindre T[3] ne coûte pas plus cher que T[0], la machine n'a pas à parcourir les cases précédentes. Ce détail paraît anodin ; c'est lui qui rendra possible la recherche dichotomique de la leçon 6.

Les cases sont numérotées de 0 à n − 1

C'est la convention de la quasi-totalité des langages, et la source d'erreur numéro un des débutants. Un tableau de 5 cases a pour indices 0, 1, 2, 3, 4. Il n'y a pas de case 5.

T[0]T[1]T[2]T[3]T[4]
1252083

La première case est T[0], la dernière est T[n − 1]n est la taille. Retenez ces deux formes plutôt que des nombres : elles restent justes quelle que soit la taille.

Accéder à T[5] sur ce tableau est un débordement d'indice. Selon le langage, le programme s'arrête net, ou — bien pire — lit un morceau de mémoire qui ne lui appartient pas et continue avec une valeur absurde.

Le parcours

Parcourir un tableau, c'est visiter ses cases une par une, dans l'ordre. Le schéma est toujours le même, et il vaut la peine de l'écrire une fois pour toutes :

Pour i de 0 à n − 1 Faire    ...traiter T[i]...FinPour

Notez n − 1, pas n. Écrire Pour i de 0 à n produit un tour de trop, et ce tour déborde. C'est l'erreur « à un près », la plus fréquente et la plus discrète du semestre.

Animation · 7 étapes

Parcourir T = [12, 5, 20, 8, 3] : somme et maximum

  1. Initialisation, avant le premier toursomme démarre à 0. max démarre à T[0], surtout pas à 0 : sur un tableau de températures négatives, un max initialisé à 0 ne serait jamais remplacé.
  2. i = 0 → T[0] = 12somme devient 0 + 12 = 12. max vaut déjà 12, rien à changer.
  3. i = 1 → T[1] = 5somme passe à 17. Test 5 > 12 ? FAUX : max ne bouge pas.
  4. i = 2 → T[2] = 2020 > 12 : c'est le seul tour où max change. Il vaudra 20 jusqu'à la fin.
  5. i = 3 → T[3] = 8somme continue de grandir, max reste à 20.
  6. i = 4 → dernière casei = 4 = n − 1 : le tableau a 5 cases numérotées de 0 à 4. Un tour de plus tenterait T[5], qui n'existe pas — c'est le débordement d'indice.
  7. Fin du parcoursLa moyenne se calcule APRÈS la boucle : 48 / 5 = 9,6. Un seul parcours a suffi pour trois résultats.

Une seule boucle a produit trois résultats. C'est un réflexe à prendre : quand plusieurs grandeurs se calculent sur les mêmes données, on ne fait pas trois parcours, on en fait un seul avec trois accumulateurs.

Quiz · 1 question

Un tableau T contient 5 valeurs. Quel est l'indice de la dernière ?

  • 5la taille du tableau
  • 4la taille moins un
  • Cela dépend des valeurssans règle fixe

Réponse : Les indices vont de 0 à n − 1, soit de 0 à 4. T[5] n'existe pas : c'est le débordement d'indice classique, et il se produit précisément quand on écrit « de 0 à n » au lieu de « de 0 à n − 1 ».

Somme, moyenne, minimum, maximum

Ces quatre calculs sont les exercices d'application obligés du parcours, et trois d'entre eux cachent un piège d'initialisation.

La somme ne pose pas de problème : accumulateur à 0, puis somme ← somme + T[i].

La moyenne se calcule après la boucle, une seule fois : moyenne ← somme / n. Diviser à l'intérieur donnerait un résultat faux à chaque tour sauf le dernier.

Le minimum et le maximum sont le vrai piège. La tentation est d'écrire :

max ← 0                          ← FAUXPour i de 0 à n − 1 Faire    Si T[i] > max Alors max ← T[i] FinSiFinPour

Sur [12, 5, 20, 8, 3], ça marche. Sur un tableau de températures hivernales [−3, −8, −5], le résultat est 0 — une température qui n'apparaît nulle part dans les données. Le maximum d'un tableau est forcément une valeur du tableau ; il faut donc partir de l'une d'elles :

max ← T[0]Pour i de 1 à n − 1 Faire    Si T[i] > max Alors max ← T[i] FinSiFinPour

Même raisonnement pour le minimum. Cette règle s'énonce simplement : on initialise avec la première valeur, jamais avec une constante inventée.

Quiz · 1 question

Avec max ← 0 au départ, que renvoie l'algorithme du maximum sur le tableau [−3, −8, −5] ?

  • −3, le vrai maximum
  • 0, qui n'est pas dans le tableau
  • −8, le minimum

Réponse : Aucune valeur du tableau n'est supérieure à 0, donc max n'est jamais remplacé et garde son initialisation. Le bug est invisible sur des données positives — c'est ce qui le rend dangereux.

Quiz · 1 question

Où placer le calcul moyenne ← somme / n ?

  • Dans la boucle, après chaque ajout
  • Après la boucle, une seule fois
  • Avant la boucle, pour initialiser

Réponse : La moyenne n'a de sens qu'une fois toutes les valeurs additionnées. La calculer dans la boucle donne n résultats intermédiaires faux — et coûte n divisions au lieu d'une.

À vous

Exercice de code

Calculez somme, minimum, maximum et moyenne en un seul parcours. Attention aux initialisations.

Point de départ

// Un seul parcours, quatre résultats.
// Consigne : écrivez la boucle sur les INDICES. Pas de reduce, pas de
// Math.min(...t) — c'est le parcours qu'on apprend ici, pas la bibliothèque.
const T = [12, -5, 20, 8, 3];

function analyser(t) {
  let somme = 0;
  let min = 0;   // ← initialisation piégée : corrigez-la
  let max = 0;   // ← celle-ci aussi

  for (let i = 0; i < t.length; i++) {
    // à compléter
  }

  return { somme, min, max, moyenne: somme / t.length };
}

console.log(analyser(T));
// attendu : { somme: 38, min: -5, max: 20, moyenne: 7.6 }

Solution

const T = [12, -5, 20, 8, 3];

function analyser(t) {
  let somme = 0;
  // On part de la PREMIÈRE VALEUR, jamais de 0 : avec un tableau de
  // températures négatives, un max initialisé à 0 ne serait jamais remplacé.
  let min = t[0];
  let max = t[0];

  for (let i = 0; i < t.length; i++) {
    somme = somme + t[i];
    if (t[i] < min) min = t[i];
    if (t[i] > max) max = t[i];
  }

  // La moyenne se calcule APRÈS la boucle, une seule fois.
  return { somme, min, max, moyenne: somme / t.length };
}

console.log(analyser(T));

À retenir

Flashcards · 2 cartes

Quels sont les indices valides d'un tableau de n cases ?
De 0 à n − 1. La première case est T[0], la dernière T[n − 1]. T[n] n'existe pas.
Comment initialiser la recherche d'un maximum ?
Avec T[0], la première valeur du tableau — jamais avec 0, qui donne un résultat faux dès que toutes les valeurs sont négatives.