Aller au contenu

Partie 1 : Parcours séquentiel et recherche dichotomique


Le parcours séquentiel (ou recherche linéaire) consiste à examiner les éléments d'un tableau un par un, du premier au dernier, jusqu'à trouver ce que l'on cherche ou atteindre la fin du tableau.

C'est l'algorithme le plus simple et le plus naturel. Il fonctionne sur n'importe quel tableau, trié ou non.

On cherche si un élément valeur est présent dans un tableau tab. Si oui, on renvoie son indice ; sinon, on renvoie -1.

def recherche(tab, valeur):
"""Renvoie l'indice de la première occurrence de valeur, ou -1."""
for i in range(len(tab)):
if tab[i] == valeur:
return i
return -1
>>> recherche([3, 7, 2, 9, 5], 9)
3
>>> recherche([3, 7, 2, 9, 5], 6)
-1
def indice_maximum(tab):
"""Renvoie l'indice du maximum d'un tableau non vide."""
assert len(tab) > 0, "Le tableau ne doit pas être vide"
i_max = 0
for i in range(1, len(tab)):
if tab[i] > tab[i_max]:
i_max = i
return i_max
>>> indice_maximum([3, 7, 2, 9, 5])
3
>>> indice_maximum([10])
0
def compter(tab, valeur):
"""Renvoie le nombre d'occurrences de valeur dans tab."""
compteur = 0
for element in tab:
if element == valeur:
compteur += 1
return compteur
def moyenne(tab):
"""Renvoie la moyenne des éléments du tableau."""
assert len(tab) > 0, "Le tableau ne doit pas être vide"
somme = 0
for element in tab:
somme += element
return somme / len(tab)
SituationNombre de comparaisons
Meilleur cas (élément en première position)1
Pire cas (élément absent ou en dernière position)n
Cas moyenn / 2

Le parcours séquentiel a une complexité en O(n) : le temps d'exécution est proportionnel à la taille du tableau.


La recherche dichotomique (du grec dikho, « en deux ») ne fonctionne que sur un tableau trié. À chaque étape, on divise l'intervalle de recherche en deux en comparant la valeur cherchée à l'élément du milieu.

C'est le principe du jeu « plus grand, plus petit ».

Cherchons la valeur 23 dans le tableau trié [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] :

Étapegauchedroitemilieutab[milieu]Action
10941623 > 16 → chercher à droite
25975623 < 56 → chercher à gauche
35652323 == 23 → trouvé !

En 3 étapes au lieu de 6 avec un parcours séquentiel.

def recherche_dichotomique(tab, valeur):
"""Recherche valeur dans tab (trié) par dichotomie.
Renvoie l'indice si trouvé, -1 sinon.
Precondition: tab est trié en ordre croissant.
"""
gauche = 0
droite = len(tab) - 1
while gauche <= droite:
milieu = (gauche + droite) // 2
if tab[milieu] == valeur:
return milieu
elif tab[milieu] < valeur:
gauche = milieu + 1
else:
droite = milieu - 1
return -1
>>> tab = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
>>> recherche_dichotomique(tab, 23)
5
>>> recherche_dichotomique(tab, 20)
-1

Pour prouver que l'algorithme se termine (ne boucle pas indéfiniment), on utilise un variant de boucle : une quantité entière qui :

  1. Est positive ou nulle à chaque itération
  2. Diminue strictement à chaque itération

Ici, le variant est droite - gauche :

  • Initialement, droite - gauche = n - 1 (positif)
  • À chaque itération, soit gauche augmente, soit droite diminue → le variant diminue
  • Quand droite - gauche < 0, la condition gauche <= droite est fausse et la boucle s'arrête

Pour prouver que l'algorithme est correct (donne le bon résultat), on utilise un invariant de boucle : une propriété vraie à chaque itération.

Invariant : « Si valeur est dans tab, alors elle se trouve à un indice compris entre gauche et droite. »

  • Initialisation : vrai car gauche = 0 et droite = len(tab) - 1 couvrent tout le tableau
  • Conservation : si tab[milieu] < valeur, la valeur est forcément à droite de milieu (car le tableau est trié), donc gauche = milieu + 1 préserve l'invariant
  • Terminaison : quand gauche > droite, l'intervalle est vide, donc la valeur n'est pas dans le tableau

À chaque étape, l'intervalle de recherche est divisé par 2.

Pour un tableau de n éléments, le nombre maximal d'étapes est ⌈log⁡2(n)⌉+1\lceil \log_2(n) \rceil + 1 :

Taille du tableauParcours séquentiel (pire cas)Dichotomie (pire cas)
10104
1001007
1 0001 00010
1 000 0001 000 00020
1 000 000 0001 000 000 00030

La recherche dichotomique a une complexité en O(log₂ n), incomparablement plus rapide que le parcours séquentiel en O(n).


  • Le parcours séquentiel examine les éléments un par un. Complexité : O(n).
  • Il permet de chercher une valeur, un extremum, de compter, de calculer une somme ou une moyenne.
  • La recherche dichotomique divise l'intervalle de recherche en deux à chaque étape. Complexité : O(log₂ n).
  • Elle nécessite un tableau trié.
  • On prouve la terminaison avec un variant de boucle (quantité qui décroît strictement).
  • On prouve la correction avec un invariant de boucle (propriété toujours vraie).