Les tris simples : sélection et insertion
Le tri par sélection
Le tri par sélection est l'algorithme le plus intuitif : à chaque étape, tu cherches le plus petit élément qui reste à trier, puis tu l'échanges avec le premier élément non trié. C'est exactement ce que tu ferais en triant des cartes à la main : tu repères la plus petite carte du paquet restant, tu la sors, tu la poses à sa place.
Le principe en détail : pour chaque position i (de 0 à n-2), tu parcours le reste du tableau (de i à n-1) pour trouver l'indice du minimum, puis tu échanges (permutes) cet élément avec celui en position i. Après le passage numéro i, les i+1 premiers éléments sont définitivement à leur place finale.
Regarde le tableau se transformer étape par étape sur l'exemple [5, 2, 4, 1, 3] :
depart : [5, 2, 4, 1, 3]
etape 0 : [1, 2, 4, 5, 3] (minimum trouve a l'indice 3, echange avec indice 0)
etape 1 : [1, 2, 4, 5, 3] (minimum du reste deja en position 1, aucun echange utile)
etape 2 : [1, 2, 3, 5, 4] (minimum trouve a l'indice 4, echange avec indice 2)
etape 3 : [1, 2, 3, 4, 5] (minimum trouve a l'indice 4, echange avec indice 3)
partie triee (a gauche) | partie a trier (a droite)
Le coût : pour chaque position i, tu parcours environ n-i éléments pour trouver le minimum. Au total, cela fait n + (n-1) + ... + 1, soit environ n²/2 comparaisons. Le tri par sélection est donc en O(n²), quel que soit l'état initial du tableau (même déjà trié, il refait toutes les comparaisons). Son avantage : très peu d'échanges (au plus n-1), ce qui est utile si échanger coûte cher.
def tri_selection(a):
a = a[:]
n = len(a)
for i in range(n - 1):
indice_min = i
for j in range(i + 1, n):
if a[j] < a[indice_min]:
indice_min = j
a[i], a[indice_min] = a[indice_min], a[i]
return a
Piège classique : oublier de mettre à jour indice_min (comparer avec a[i] au lieu de a[indice_min]), ce qui casse la recherche du minimum.

