L[0:k].L[0:i+1] sont triés entre eux.| Code erroné | Code correct | Explication |
|---|---|---|
L2 = L.sort() puis utiliser L2 | L2 = sorted(L) | .sort() trie en place et renvoie None ; sorted() renvoie une nouvelle liste triée. L2 vaut donc None. |
Tri par sélection : L[i] = L[i_min] L[i_min] = L[i] | L[i], L[i_min] = L[i_min], L[i] | Sans échange simultané, la première ligne écrase L[i] : on perd la valeur qui devait aller dans L[i_min]. |
Tri par insertion : while L[j] > cle: sans j >= 0 | while j >= 0 and L[j] > cle: | Sans la condition j >= 0, on accède à L[-1] (dernier élément en Python) au lieu de s'arrêter : résultat faux. |
for i in range(n): dans le tri par sélection | for i in range(n - 1): | La boucle externe va jusqu'à $n-2$ car le dernier élément est automatiquement en place quand tous les autres sont triés. |
def tri_selection(L):
n = len(L)
for i in range(n - 1):
i_min = i
for j in range(i + 1, n):
if L[j] < L[i_min]:
i_min = j
L[i], L[i_min] = L[i_min], L[i]
Trace sur [5, 3, 8, 1, 4] :
| Étape | Zone non triée | Min trouvé | Liste après échange |
|---|---|---|---|
| 1 | {[}5, 3, 8, 1, 4{]} | 1 (indice 3) | {[}1, 3, 8, 5, 4{]} |
| 2 | {[}3, 8, 5, 4{]} | 3 (en place) | {[}1, 3, 8, 5, 4{]} |
| 3 | {[}8, 5, 4{]} | 4 (indice 4) | {[}1, 3, 4, 5, 8{]} |
| 4 | {[}5, 8{]} | 5 (en place) | {[}1, 3, 4, 5, 8{]} |
def tri_insertion(L):
for i in range(1, len(L)):
cle = L[i]
j = i - 1
while j >= 0 and L[j] > cle:
L[j + 1] = L[j]
j -= 1
L[j + 1] = cle
Trace sur [5, 3, 8, 1, 4] :
| Étape | Clé | Décalages | Liste après insertion |
|---|---|---|---|
| 1 | 3 | 5 décalé | {[}3, 5, 8, 1, 4{]} |
| 2 | 8 | aucun | {[}3, 5, 8, 1, 4{]} |
| 3 | 1 | 8, 5, 3 décalés | {[}1, 3, 5, 8, 4{]} |
| 4 | 4 | 8, 5 décalés | {[}1, 3, 4, 5, 8{]} |
Donner l'état de la liste [7, 2, 5, 1, 3] après chaque passage du tri par sélection. Indiquer à chaque étape quel échange est effectué.
[7, 2, 5, 1, 3] = 1 (indice 3). Échange L[0] et L[3] : [1, 2, 5, 7, 3].[2, 5, 7, 3] = 2 (indice 1), déjà en place : [1, 2, 5, 7, 3].[5, 7, 3] = 3 (indice 4). Échange L[2] et L[4] : [1, 2, 3, 7, 5].[7, 5] = 5 (indice 4). Échange L[3] et L[4] : [1, 2, 3, 5, 7].Nombre total de comparaisons : $4 + 3 + 2 + 1 = 10 = \frac{5 \times 4}{2}$.
Donner l'état de la liste [6, 2, 8, 4, 1] après chaque insertion. Indiquer à chaque étape le nombre de décalages.
[2, 6, 8, 4, 1]. (1 décalage.)[2, 6, 8, 4, 1]. (0 décalage.)[2, 4, 6, 8, 1]. (2 décalages.)[1, 2, 4, 6, 8]. (4 décalages.)Total des décalages : $1 + 0 + 2 + 4 = 7$.
Écrire une fonction est_triee(L) qui renvoie True si L est triée par ordre croissant (au sens large), False sinon.
def est_triee(L):
for i in range(len(L) - 1):
if L[i] > L[i + 1]:
return False
return True
Principe : on compare chaque élément au suivant. Dès qu'on trouve L[i] > L[i+1], la liste n'est pas triée.
Vérification : est_triee([1, 1, 2, 3]) renvoie True ; est_triee([1, 3, 2]) renvoie False ; est_triee([]) et est_triee([5]) renvoient True.
tri_selection_compteur(L) qui trie et renvoie le nombre de comparaisons.tri_insertion_compteur(L) qui trie et renvoie le nombre de comparaisons.def tri_selection_compteur(L):
L = L[:]
n, nb = len(L), 0
for i in range(n - 1):
i_min = i
for j in range(i + 1, n):
nb += 1
if L[j] < L[i_min]:
i_min = j
L[i], L[i_min] = L[i_min], L[i]
return nb
def tri_insertion_compteur(L):
L = L[:]
nb = 0
for i in range(1, len(L)):
cle = L[i]
j = i - 1
while j >= 0:
nb += 1
if L[j] > cle:
L[j + 1] = L[j]
j -= 1
else:
break
L[j + 1] = cle
return nb
Résultats pour $n = 20$ :
Conclusion : le tri par insertion s'adapte à l'état initial de la liste, pas le tri par sélection.