Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 725 minDébutant

Tableaux et listes : les algorithmes de base

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • créer un tableau, accéder à un élément et le parcourir ;
  • calculer une somme, une moyenne, un maximum ou un nombre d'occurrences ;
  • rechercher un élément et renvoyer sa position ;
  • ajouter, insérer, supprimer et copier des éléments sans effet de bord.

7 exercices corrigés1 schéma

Un tableau est une structure qui range plusieurs valeurs sous un seul nom, chacune repérée par sa position, appelée indice ; en Python, on utilise pour cela une liste. Ce chapitre montre comment construire un tableau, accéder à ses éléments, le parcourir, et écrire les algorithmes qui reviennent dans tous les sujets : somme, moyenne, maximum, comptage, recherche, insertion, suppression et copie.

Pourquoi des tableaux ?

Pour calculer la moyenne de trois notes, trois variables suffisent. Pour trente notes, il en faudrait trente, et autant de lignes de calcul. Et si le nombre de notes change, il faut réécrire le programme. Un tableau regroupe toutes les notes dans une seule variable ; une boucle les traite toutes, quel que soit leur nombre.

Indice01234
notes14917119

Le tableau notes a 5 éléments, d'indices 0 à 4. L'élément d'indice 2, noté notes[2], vaut 17. Un tableau de n éléments a des indices de 0 à n - 1 : le dernier indice n'est pas n.

Construire un tableau

En pseudo-code, on déclare le tableau avec sa taille et le type de ses éléments. Le programme parle de tableaux « de type homogène » : toutes les cases ont le même type.

text
Variables
    notes : tableau[0..4] de réels
Début
    notes[0] ← 14
    notes[1] ← 9
    ...

En Python, un tableau à une dimension est une liste. Elle n'a pas de taille fixe et peut grandir : on peut la créer de plusieurs façons.

python
notes = [14, 9, 17, 11, 9]   # en donnant ses valeurs
zeros = [0] * 5              # 5 cases à 0 : [0, 0, 0, 0, 0]
releves = []                 # vide, puis on ajoute
releves.append(21.5)
releves.append(19.0)
print(notes, zeros, releves, len(notes))
text
[14, 9, 17, 11, 9] [0, 0, 0, 0, 0] [21.5, 19.0] 5

len(t) donne le nombre d'éléments. t.append(x) ajoute x à la fin : c'est la façon normale de remplir une liste dans une boucle, par exemple à partir de saisies.

python
n = int(input("Combien de notes ? "))
notes = []
for i in range(n):
    notes.append(float(input(f"Note {i + 1} ? ")))

Accéder à un élément

On lit ou on modifie un élément par son indice, entre crochets.

python
notes = [14, 9, 17, 11, 9]
print(notes[0], notes[4])   # premier et dernier
notes[1] = 10               # modification
print(notes)
print(notes[-1])            # Python : le dernier élément
text
14 9
[14, 10, 17, 11, 9]
9

Les indices négatifs sont une facilité de Python (t[-1] est le dernier élément, t[-2] l'avant-dernier) ; ils n'existent pas en pseudo-code ni dans la plupart des langages. En algorithmique, écris t[n - 1].

Parcourir un tableau

Parcourir, c'est visiter chaque élément une fois, dans l'ordre. Deux écritures existent en Python.

Par indice, quand tu as besoin de la position (pour la renvoyer, pour comparer un élément à son voisin, pour modifier la case) :

text
Pour i de 0 à longueur(t) - 1 Faire
    Afficher(i, " : ", t[i])
FinPour
python
t = [14, 9, 17]
for i in range(len(t)):
    print(i, ":", t[i])

Par valeur, quand seule la valeur compte (somme, comptage) :

python
t = [14, 9, 17]
for note in t:
    print(note)

La seconde est plus lisible et ne peut pas déborder du tableau. Quand tu as besoin des deux, enumerate donne l'indice et la valeur à chaque tour : for i, note in enumerate(t):.

BesoinParcours
Somme, comptage, test d'appartenancePar valeur
Renvoyer la position d'un élémentPar indice (ou enumerate)
Modifier les cases du tableauPar indice : t[i] = …
Comparer un élément à son voisinPar indice, de 1 à n − 1 (pour que t[i - 1] existe)

Somme et moyenne

C'est le motif de l'accumulateur (chapitre 4) appliqué à un tableau.

text
Fonction Moyenne(t : tableau de réels) : réel
// Précondition : t n'est pas vide
    somme ← 0
    Pour i de 0 à longueur(t) - 1 Faire
        somme ← somme + t[i]
    FinPour
    Retourner somme / longueur(t)
FinFonction
python
def moyenne(t):
    """Moyenne d'une liste non vide de nombres."""
    somme = 0
    for valeur in t:
        somme = somme + valeur
    return somme / len(t)


print(moyenne([14, 9, 17, 11, 9]))
text
12.0

Maximum et minimum

Pour trouver le plus grand élément, on garde « le plus grand vu jusqu'ici » et on le compare à chaque élément suivant.

text
Fonction Maximum(t : tableau de réels) : réel
// Précondition : t n'est pas vide
    maxi ← t[0]
    Pour i de 1 à longueur(t) - 1 Faire
        Si t[i] > maxi Alors
            maxi ← t[i]
        FinSi
    FinPour
    Retourner maxi
FinFonction
python
def maximum(t):
    maxi = t[0]
    for i in range(1, len(t)):
        if t[i] > maxi:
            maxi = t[i]
    return maxi


print(maximum([14, 9, 17, 11, 9]), maximum([-3, -8, -1]))
text
17 -1

Pour le minimum, on inverse la comparaison (<). Souvent, on veut la position du maximum plutôt que sa valeur, par exemple pour afficher le nom de l'étudiant qui a la meilleure note. On garde alors l'indice :

python
def indice_du_max(t):
    i_max = 0
    for i in range(1, len(t)):
        if t[i] > t[i_max]:
            i_max = i
    return i_max


noms = ["Inès", "Hugo", "Léa", "Malik"]
notes = [14, 9, 17, 11]
i = indice_du_max(notes)
print(noms[i], "a la meilleure note :", notes[i])
text
Léa a la meilleure note : 17

En cas d'égalité, > garde le premier maximum rencontré ; avec >=, on garderait le dernier.

Compter

Le compteur s'incrémente quand un élément vérifie une condition.

python
notes = [14, 9, 17, 11, 9]
nb_sous_la_moyenne = 0
for note in notes:
    if note < 10:
        nb_sous_la_moyenne = nb_sous_la_moyenne + 1
print(nb_sous_la_moyenne)
text
2

Beaucoup d'énoncés sont des comptages déguisés : « combien de tickets sont ouverts », « y a-t-il au moins un serveur hors ligne » (compter, puis tester nb > 0), « tous les postes sont-ils à jour » (compter ceux qui ne le sont pas, puis tester nb = 0).

Rechercher un élément

La recherche séquentielle parcourt le tableau jusqu'à trouver la valeur cherchée. Elle fonctionne sur n'importe quel tableau, trié ou non. On renvoie l'indice de la première occurrence, ou −1 par convention si la valeur est absente.

En pseudo-code, une boucle TantQue exprime clairement les deux raisons de s'arrêter : on a trouvé, ou on est au bout.

text
Fonction Rechercher(t : tableau d'entiers, x : entier) : entier
    i ← 0
    trouve ← FAUX
    TantQue i < longueur(t) ET NON trouve Faire
        Si t[i] = x Alors
            trouve ← VRAI
        Sinon
            i ← i + 1
        FinSi
    FinTantQue
    Si trouve Alors
        Retourner i
    Sinon
        Retourner -1
    FinSi
FinFonction

En Python, un return dans la boucle donne une version plus courte :

python
def rechercher(t, x):
    for i in range(len(t)):
        if t[i] == x:
            return i
    return -1


ports = [22, 80, 443, 3306]
print(rechercher(ports, 443), rechercher(ports, 21))
text
2 -1

Dans le pire cas (valeur absente ou en dernière position), la recherche séquentielle examine tous les éléments. Sur un tableau trié, la recherche dichotomique fait beaucoup mieux (chapitre 10).

Ajouter, insérer, supprimer

En pseudo-code, un tableau a une taille fixe. Insérer une valeur au milieu oblige à décaler les éléments suivants d'une case vers la droite, en partant de la fin pour ne rien écraser. C'est un exercice classique, qui montre pourquoi l'insertion « coûte » plus cher qu'un ajout en fin de tableau.

text
// t contient n éléments utiles, dans un tableau d'au moins n + 1 cases.
// Insère x à l'indice p (0 ≤ p ≤ n).
Pour i de n à p + 1 pas -1 Faire
    t[i] ← t[i - 1]
FinPour
t[p] ← x
n ← n + 1

Python fait ce travail pour toi avec ses méthodes de liste :

OpérationPythonEffet sur t = [1, 2, 3, 4, 5]
Ajouter à la fint.append(6)[1, 2, 3, 4, 5, 6]
Insérer à une positiont.insert(1, 10)[1, 10, 2, 3, 4, 5]
Retirer et renvoyer le derniert.pop()renvoie 5, t devient [1, 2, 3, 4]
Retirer à une positiont.pop(0) ou del t[0][2, 3, 4, 5]
Retirer une valeur (la première)t.remove(3)[1, 2, 4, 5] ; ValueError si absente

Ces méthodes décalent les éléments en interne : insert et pop(0) sont plus lentes que append et pop() sur une très longue liste.

Copier un tableau

C'est le piège le plus surprenant de Python. L'affectation b = a ne copie pas la liste : elle donne un second nom à la même liste. Toute modification par b est visible par a.

python
a = [3, 8, 5]
b = a          # b désigne la même liste que a
b[0] = 99
print(a)

a = [3, 8, 5]
c = a.copy()   # c est une nouvelle liste, avec les mêmes valeurs
c[0] = 99
print(a, c)
text
[99, 8, 5]
[3, 8, 5] [99, 8, 5]
b = apuis b[0] = 99ab9985une seule liste :a voit aussi le 99c = a.copy()puis c[0] = 99ac3859985deux listes distinctes :a ne change pas
b = a crée un second nom pour la même liste ; a.copy() crée une nouvelle liste

Une variable Python ne contient pas la liste elle-même, mais une référence vers elle (une sorte d'adresse). b = a copie la référence. Pour copier les valeurs, utilise a.copy(), list(a) ou a[:]. C'est le même mécanisme qui permet à une fonction de modifier une liste reçue en paramètre (chapitre 6). Le programme demande de savoir « copier un tableau » : en pseudo-code, on l'écrit avec une boucle qui recopie chaque case.

text
Pour i de 0 à longueur(a) - 1 Faire
    copie[i] ← a[i]
FinPour

Les nombres et les chaînes, eux, ne posent pas ce problème : on ne peut pas les modifier sur place, donc partager une référence est sans danger.

Les fonctions toutes faites de Python

Python fournit la plupart de ces algorithmes en une instruction. En situation professionnelle, on s'en sert ; à l'examen, on te demande souvent l'algorithme : connais les deux.

BesoinFonction PythonAlgorithme à savoir écrire
Nombre d'élémentslen(t)
Sommesum(t)Accumulateur
Maximum, minimummax(t), min(t)Maximum courant initialisé au premier élément
Appartenancex in tRecherche séquentielle
Positiont.index(x) (ValueError si absent)Recherche séquentielle, −1 si absent
Nombre d'occurrencest.count(x)Compteur
Trisorted(t) (nouvelle liste), t.sort() (sur place)Tris du chapitre 10

Python propose aussi les listes en compréhension, une écriture compacte pour construire une liste à partir d'une autre : [n * 2 for n in t] double chaque élément, [n for n in t if n >= 10] filtre. Elles sont courantes en Python professionnel ; la boucle avec append fait exactement la même chose et reste la forme à maîtriser.

Exercices

Exercice 1 sur 7 Trace d'un parcours Réussi À revoir

Fais la trace de ce programme et donne l'affichage. Que fait-il ?

python
t = [5, 12, 7, 3, 12]
k = 0
for i in range(1, len(t)):
    if t[i] > t[k]:
        k = i
print(k, t[k])
Voir la réponseMasquer la réponse de l'exercice 1
it[i]t[k] avantt[i] > t[k] ?k
avant0
1125oui1
2712non1
3312non1
41212non1

Affichage : 1 12. Le programme cherche l'indice du premier maximum du tableau. Le second 12, à l'indice 4, n'est pas retenu car la comparaison est stricte.

Tu avais trouvé ?

Exercice 2 sur 7 Au-dessus de la moyenne Réussi À revoir

Écris une fonction nb_au_dessus_moyenne(t) qui renvoie le nombre d'éléments strictement supérieurs à la moyenne du tableau. Pourquoi faut-il deux parcours ? Teste avec [14, 9, 17, 11, 9].

Voir la réponseMasquer la réponse de l'exercice 2
python
def nb_au_dessus_moyenne(t):
    somme = 0
    for v in t:
        somme = somme + v
    moy = somme / len(t)
    nb = 0
    for v in t:
        if v > moy:
            nb = nb + 1
    return nb


print(nb_au_dessus_moyenne([14, 9, 17, 11, 9]))

La moyenne vaut 60 / 5 = 12 ; 14 et 17 sont au-dessus : la fonction renvoie 2. Il faut deux parcours, car on ne connaît la moyenne qu'après avoir vu tous les éléments : impossible de comparer pendant le premier.

Tu avais trouvé ?

Exercice 3 sur 7 Inverser un tableau sur place Réussi À revoir

Écris l'algorithme qui inverse l'ordre des éléments d'un tableau sans créer de second tableau : [4, 7, 1, 9, 3] devient [3, 9, 1, 7, 4]. Combien d'échanges pour un tableau de n éléments ?

Voir la réponseMasquer la réponse de l'exercice 3

On échange le premier et le dernier, puis le deuxième et l'avant-dernier, et ainsi de suite jusqu'au milieu.

text
n ← longueur(t)
Pour i de 0 à n DIV 2 - 1 Faire
    temp ← t[i]
    t[i] ← t[n - 1 - i]
    t[n - 1 - i] ← temp
FinPour
python
t = [4, 7, 1, 9, 3]
n = len(t)
for i in range(n // 2):
    t[i], t[n - 1 - i] = t[n - 1 - i], t[i]
print(t)

Il faut n DIV 2 échanges : 2 pour 5 éléments (l'élément du milieu reste en place). Si la boucle allait jusqu'au bout, chaque paire serait échangée deux fois, et le tableau reviendrait à son état initial.

Tu avais trouvé ?

Exercice 4 sur 7 Supprimer les doublons Réussi À revoir

Écris une fonction qui renvoie une nouvelle liste contenant les éléments de t sans doublon, dans l'ordre de leur première apparition. Pour [12, 5, 7, 5, 12, 3], le résultat est [12, 5, 7, 3].

Voir la réponseMasquer la réponse de l'exercice 4
python
def sans_doublons(t):
    resultat = []
    for v in t:
        if v not in resultat:
            resultat.append(v)
    return resultat


print(sans_doublons([12, 5, 7, 5, 12, 3]))

Le test v not in resultat est lui-même une recherche séquentielle dans resultat. En pseudo-code, on l'écrirait avec la fonction Rechercher du cours : Si Rechercher(resultat, v) = -1 Alors ….

Tu avais trouvé ?

Exercice 5 sur 7 Le tableau est-il trié ? Réussi À revoir

Écris une fonction est_trie(t) qui renvoie True si le tableau est trié dans l'ordre croissant (au sens large). Donne un jeu d'essai de cinq cas, dont deux cas limites.

Voir la réponseMasquer la réponse de l'exercice 5
python
def est_trie(t):
    for i in range(1, len(t)):
        if t[i] < t[i - 1]:
            return False
    return True


assert est_trie([2, 5, 5, 9]) == True    # cas normal, avec égalité
assert est_trie([2, 9, 5]) == False      # cas normal non trié
assert est_trie([9, 2]) == False         # défaut au tout début
assert est_trie([]) == True              # cas limite : vide
assert est_trie([7]) == True             # cas limite : un élément
print("OK")

Dès qu'une « descente » est trouvée, on renvoie False. Pour une liste vide ou d'un élément, la boucle ne fait aucun tour et la fonction renvoie True : une liste sans paire d'éléments est triée.

Tu avais trouvé ?

Exercice 6 sur 7 Copie ou pas copie ? Réussi À revoir

Qu'affiche ce programme ?

python
def ajouter_bonus(notes):
    for i in range(len(notes)):
        notes[i] = notes[i] + 1


classe = [12, 8, 15]
sauvegarde = classe
ajouter_bonus(classe)
print(classe, sauvegarde)
Voir la réponseMasquer la réponse de l'exercice 6

[13, 9, 16] [13, 9, 16]. sauvegarde = classe ne copie rien : les deux noms désignent la même liste. La fonction modifie cette liste sur place (paramètre en entrée-sortie), donc les deux noms montrent les notes augmentées. Pour une vraie sauvegarde, il fallait sauvegarde = classe.copy() avant l'appel.

Tu avais trouvé ?

Exercice 7 sur 7 Décalage circulaire Réussi À revoir

Écris l'algorithme qui décale tous les éléments d'un tableau d'une case vers la droite, le dernier revenant en première position : [1, 2, 3, 4] devient [4, 1, 2, 3]. Utilise une seule variable temporaire, et fais attention au sens du parcours.

Voir la réponseMasquer la réponse de l'exercice 7

On met le dernier élément de côté, on décale en partant de la fin (sinon chaque case écraserait la suivante avant qu'on l'ait déplacée), puis on place le dernier en tête.

python
t = [1, 2, 3, 4]
n = len(t)
dernier = t[n - 1]
for i in range(n - 1, 0, -1):
    t[i] = t[i - 1]
t[0] = dernier
print(t)

Si l'on parcourait de gauche à droite, t[1] ← t[0] puis t[2] ← t[1] recopierait la valeur 1 partout : on obtiendrait [4, 1, 1, 1].

Tu avais trouvé ?

Chapitre terminé !

Fais les 7 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Tableaux à deux dimensions, matrices et dictionnairesRevoir le sommaire du cours