Partie 2 : Algorithmes de tri
1. Pourquoi trier ?
Section intitulée « 1. Pourquoi trier ? »Le tri est l'une des opérations les plus fondamentales en informatique. Trier des données permet ensuite de :
- Faire une recherche dichotomique (beaucoup plus rapide)
- Éliminer les doublons
- Calculer la médiane
- Afficher un classement, un palmarès
On étudie ici deux algorithmes simples qui trient un tableau en place (sans créer de nouveau tableau).
2. Tri par sélection
Section intitulée « 2. Tri par sélection »2.1 Principe
Section intitulée « 2.1 Principe »À chaque étape, on sélectionne le plus petit élément parmi ceux qui ne sont pas encore triés, et on le place à sa position définitive.
- Chercher le minimum du tableau
[0 .. n-1]et l'échanger avec l'élément en position 0 - Chercher le minimum du tableau
[1 .. n-1]et l'échanger avec l'élément en position 1 - Ainsi de suite jusqu'à la fin
2.2 Déroulement d'un exemple
Section intitulée « 2.2 Déroulement d'un exemple »Tableau initial : [64, 25, 12, 22, 11]
| Étape | Partie triée | Partie non triée | Min trouvé | Échange |
|---|---|---|---|---|
| 1 | [] | [64, 25, 12, 22, 11] | 11 (indice 4) | 64 ↔ 11 |
| 2 | [11] | [25, 12, 22, 64] | 12 (indice 2) | 25 ↔ 12 |
| 3 | [11, 12] | [25, 22, 64] | 22 (indice 3) | 25 ↔ 22 |
| 4 | [11, 12, 22] | [25, 64] | 25 (indice 3) | pas d'échange |
Résultat : [11, 12, 22, 25, 64]
2.3 Implémentation
Section intitulée « 2.3 Implémentation »def tri_selection(tab): """Trie le tableau tab en place par sélection.""" n = len(tab) for i in range(n - 1): i_min = i for j in range(i + 1, n): if tab[j] < tab[i_min]: i_min = j tab[i], tab[i_min] = tab[i_min], tab[i]>>> t = [64, 25, 12, 22, 11]>>> tri_selection(t)>>> t[11, 12, 22, 25, 64]2.4 Correction (invariant de boucle)
Section intitulée « 2.4 Correction (invariant de boucle) »Invariant : « Après l'itération i, les éléments tab[0..i] sont triés et sont les i+1 plus petits éléments du tableau. »
- Initialisation (i = 0) :
tab[0]contient le minimum du tableau entier → vrai - Conservation : à l'étape i, on place le minimum de
tab[i..n-1]en position i. Les élémentstab[0..i-1]sont déjà triés et tous ≤tab[i], donctab[0..i]est trié → vrai - Terminaison : quand i = n-2, tout le tableau est trié
2.5 Complexité
Section intitulée « 2.5 Complexité »La boucle interne parcourt :
- n-1 éléments, puis n-2, puis n-3, ..., puis 1
Total de comparaisons :
La complexité est en O(n²), quel que soit le tableau (meilleur cas = pire cas).
3. Tri par insertion
Section intitulée « 3. Tri par insertion »3.1 Principe
Section intitulée « 3.1 Principe »Le tri par insertion fonctionne comme on trie un jeu de cartes dans sa main : on prend les cartes une par une et on insère chacune à sa bonne place dans la partie déjà triée.
- L'élément en position 0 est « trié » (il est seul)
- On prend l'élément en position 1 et on l'insère à sa place dans
[0..0] - On prend l'élément en position 2 et on l'insère à sa place dans
[0..1] - Ainsi de suite
3.2 Déroulement d'un exemple
Section intitulée « 3.2 Déroulement d'un exemple »Tableau initial : [5, 2, 4, 6, 1, 3]
| Étape | Clé | Partie triée | Insertion | Résultat |
|---|---|---|---|---|
| 1 | 2 | [5] | 2 < 5, décaler | [2, 5, 4, 6, 1, 3] |
| 2 | 4 | [2, 5] | 4 < 5, 4 > 2 | [2, 4, 5, 6, 1, 3] |
| 3 | 6 | [2, 4, 5] | 6 > 5, en place | [2, 4, 5, 6, 1, 3] |
| 4 | 1 | [2, 4, 5, 6] | tout décaler | [1, 2, 4, 5, 6, 3] |
| 5 | 3 | [1, 2, 4, 5, 6] | 3 entre 2 et 4 | [1, 2, 3, 4, 5, 6] |
3.3 Implémentation
Section intitulée « 3.3 Implémentation »def tri_insertion(tab): """Trie le tableau tab en place par insertion.""" for i in range(1, len(tab)): cle = tab[i] j = i - 1 while j >= 0 and tab[j] > cle: tab[j + 1] = tab[j] j = j - 1 tab[j + 1] = cle>>> t = [5, 2, 4, 6, 1, 3]>>> tri_insertion(t)>>> t[1, 2, 3, 4, 5, 6]3.4 Correction (invariant de boucle)
Section intitulée « 3.4 Correction (invariant de boucle) »Invariant : « Après l'itération i, le sous-tableau tab[0..i] contient les mêmes éléments qu'initialement, mais triés en ordre croissant. »
- Initialisation (i = 1) :
tab[0..1]contient 2 éléments en ordre → vrai - Conservation : on insère
tab[i]à sa bonne place danstab[0..i-1](déjà trié), donctab[0..i]est trié → vrai - Terminaison : quand i = n-1,
tab[0..n-1]est trié
3.5 Complexité
Section intitulée « 3.5 Complexité »| Cas | Situation | Comparaisons | Complexité |
|---|---|---|---|
| Meilleur | Tableau déjà trié | n - 1 | O(n) |
| Pire | Tableau trié à l'envers | O(n²) | |
| Moyen | Tableau aléatoire | O(n²) |
Le tri par insertion est plus rapide que le tri par sélection sur un tableau presque trié.
4. Comparaison des deux algorithmes
Section intitulée « 4. Comparaison des deux algorithmes »| Critère | Tri par sélection | Tri par insertion |
|---|---|---|
| Complexité pire cas | O(n²) | O(n²) |
| Complexité meilleur cas | O(n²) | O(n) |
| Nombre d'échanges (pire cas) | O(n) | O(n²) |
| Stable (conserve l'ordre des égaux) | Non | Oui |
| Adaptatif (plus rapide si presque trié) | Non | Oui |
| En place (pas de mémoire supplémentaire) | Oui | Oui |
5. Vérification expérimentale
Section intitulée « 5. Vérification expérimentale »On peut mesurer le temps d'exécution pour comparer les algorithmes :
import timeimport random
def mesurer_temps(fonction_tri, taille): tab = [random.randint(0, 10000) for _ in range(taille)] debut = time.time() fonction_tri(tab) fin = time.time() return fin - debut
for n in [100, 1000, 5000, 10000]: t_sel = mesurer_temps(tri_selection, n) t_ins = mesurer_temps(tri_insertion, n) print(f"n={n:6d} sélection: {t_sel:.4f}s insertion: {t_ins:.4f}s")On observe que quand n est multiplié par 10, le temps est multiplié par environ 100 (confirmation du O(n²)).
Visualisation animée des tris : activez JavaScript pour utiliser cette visualisation.
À retenir
Section intitulée « À retenir »- Le tri par sélection cherche le minimum à chaque étape et le place en tête. Complexité : O(n²) dans tous les cas.
- Le tri par insertion insère chaque élément à sa place dans la partie déjà triée. Complexité : O(n²) dans le pire cas, mais O(n) si le tableau est presque trié.
- Les deux algorithmes trient en place (pas de tableau supplémentaire).
- On prouve la correction d'un tri avec un invariant de boucle.
- La terminaison est garantie par des boucles bornées.
- Le tri par insertion est stable (conserve l'ordre des égaux), pas le tri par sélection.
© 2026 Corentin Dupont - LyCode
Créé avec Astro Starlight