On écrit le programme de tri par sélection comme suit :
def indice_du_min(liste, depart):
"""
renvoie l'indice d'une valeur minimale
parmi liste[depart], liste[depart+1], liste[depart+2], ..., liste[len(liste)-1]
"""
valeur_min = liste[depart]
indice = depart
for i in range(depart+1, len(liste)):
if liste[i] < valeur_min :
valeur_min, indice = liste[i], i
return indice
def tri_selection(liste) :
for i in range(len(liste)-1):
m = indice_du_min(liste, i)
liste[i], liste[m] = liste[m], liste[i]
- Dans le programme précédent, comptez, en fonction de n = longueur de la liste donnée en entrée, le nombre de comparaisons qui a lieu entre deux éléments de la liste.
- Vous compterez également le nombre d'échanges entre deux éléments de la liste et le nombre d'affectations.
- Que peut-on dire du temps de calcul nécessaire à un tri de liste avec cet algorithme ?
- Question 1
- Question 2
- Question 3
Les comparaisons entre éléments de la liste se font dans la fonction indice_du_min.
def indice_du_min(liste, depart):
valeur_min = liste[depart]
indice = depart
for i in range(depart+1, len(liste)):
if liste[i] < valeur_min :
valeur_min, indice = liste[i], i
return indice
Dans cette fonction, on compare les éléments liste[depart+1], liste[depart+2], ..., liste[len(liste)-1] à une valeur
valeur_min.
Le nombre de comparaisons est, dans cette fonction, égal à len(liste)-1-depart = n-1-depart en notant n la longueur de la liste à trier.
Cette fonction est appelée dans la procédure tri_selection.
def tri_selection(liste) :
for i in range(len(liste)-1):
m = indice_du_min(liste, i)
liste[i], liste[m] = liste[m], liste[i]
Elle est appelée avec les valeurs de depart = i : 0, 1, 2, ..., len(liste)-2.
Le nombre total de comparaisons est donc : \[ C_n = \sum_{i=0}^{n-2} (n-1-i) \] \[ C_n = (n-1)+(n-2)+(n-3)+ \dots + 1 \] On reconnaît là une progression arithmétique : \[ C_n = \frac{1}{2} n (n-1) \]
Nombre d'échanges
Les échanges entre deux éléments de la liste se font dans la procédure tri_selection.
def tri_selection(liste) :
for i in range(len(liste)-1):
m = indice_du_min(liste, i)
liste[i], liste[m] = liste[m], liste[i]
Nombre d'affectations
Les affectations que l'on n'a pas déjà comptées dans les échanges ci-dessus se font dans la fonction indice_du_min.
def indice_du_min(liste, depart):
valeur_min = liste[depart]
indice = depart
for i in range(depart+1, len(liste)):
if liste[i] < valeur_min :
valeur_min, indice = liste[i], i
return indice
Comme cette fonction indice_du_min est appelée par la fonction tri_selection pour les valeurs i = 0, 1, 2, ..., n-2, le nombre de ces affectations est d'au plus : \[ A_n = \sum_{i = 0}^{n-2} 2\times(n-i) \] \[A_n = 2\times (n+(n-1)+(n-2)+\dots + 2) \] soit \[A_n = (n-1)(n+2)\]
On part de l'idée (à peu près correcte) que toute comparaison demandera toujours le même temps c, toute affectation le même temps a, tout échange d'éléments dans la liste le même temps e.
On a donc un temps d'exécution total majoré par : \[ T_n = c\times \frac{1}{2} n (n-1) + e \times (n-2) + a \times (n-1)(n+2) \] et (les comparaisons étant effectuées systématiquement) minoré par \[ T_n = c\times \frac{1}{2} n (n-1) \] Le temps d'exécution est donc compris entre deux polynômes de degré deux. C'est ce que l'on nomme une complexité temporelle quadratique.