Probleme – Le tri rapide : pourquoi il gagne en moyenne et perd au pire
Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 15 — Diviser pour régner
Énoncé
Le cours signale que le tri rapide « dégénère en sur les pires entrées ». On regarde de près.
- Écrire le tri rapide avec partition en place et pivot en dernière position.
- Exhiber son pire cas et compter ses comparaisons et sa profondeur de récursion.
- Proposer une parade et la mesurer.
- Pourquoi l'emploie-t-on malgré tout plus que le tri par partition-fusion ?
Corrigé
1. Le tri.
(* Trie t.[g .. d] en place. Précondition : 0 <= g, d < |t|.
Complexité : Theta(n log n) en moyenne, Theta(n^2) au pire. *)
let echanger t i j = let x = t.(i) in t.(i) <- t.(j); t.(j) <- x
let rec trier t g d =
if g < d then begin
let pivot = t.(d) in
let i = ref g in
(* INVARIANT : t.[g .. i-1] <= pivot, et t.[i .. j-1] > pivot. *)
for j = g to d - 1 do
if t.(j) <= pivot then begin echanger t !i j; incr i end
done;
echanger t !i d; (* le pivot prend sa place DÉFINITIVE *)
trier t g (!i - 1);
trier t (!i + 1) d
end
Terminaison : variant ; le pivot étant placé définitivement, les deux appels portent sur des intervalles strictement plus courts. Correction : l'invariant garantit qu'après la boucle, tout ce qui est à gauche de est pivot et tout ce qui est à droite est ; le pivot y est donc à sa place finale, et il suffit de trier les deux côtés.
2. Le pire cas. C'est le tableau déjà trié : le pivot, pris en dernière position, est alors le maximum, la partition ne sépare rien, et l'on récurse sur éléments. D'où .
| comparaisons | profondeur | ||
|---|---|---|---|
| 64 | 64 | ||
| 256 | 256 | ||
Le compte est exactement : le tri rapide devient un tri par sélection.
Et le second défaut est pire que le premier : la profondeur de récursion vaut . À , la pile d'exécution du chapitre chap:recursivite déborde, et le programme ne rend pas un mauvais résultat — il s'arrête. Le pire cas du tri rapide n'est pas une lenteur, c'est un plantage, et il survient sur l'entrée la plus banale qui soit : des données déjà en ordre.
3. La parade : le médian de trois. On prend pour pivot la médiane de , et , et on l'échange en position avant de partitionner.
let median3 t g d =
let m = g + (d - g) / 2 in
let a = t.(g) and b = t.(m) and c = t.(d) in
if (a <= b && b <= c) || (c <= b && b <= a) then m
else if (b <= a && a <= c) || (c <= a && a <= b) then g else d
| tableau trié | tableau aléatoire | |||
|---|---|---|---|---|
| pivot = dernier | médian de 3 | pivot = dernier | médian de 3 | |
| (prof. ) | (prof. 11) | |||
| (prof. ) | (prof. 13) | |||
| --- | --- |
Sur un tableau trié, le médian de trois choisit le vrai milieu : les partitions sont parfaites, la profondeur tombe à , et le coût à . Sur des données aléatoires, le gain n'est que de quelques pour cent — c'est normal, un pivot tiré au hasard y est déjà bon.
Mais le médian de trois ne supprime pas le pire cas, il le déplace : il existe des tableaux, construits exprès, qui le mettent en défaut. Les seules parades garanties sont le pivot tiré au hasard (chapitre chap:probabilistes) — dont le pire cas devient improbable au lieu d'impossible — ou le basculement sur un tri par tas au-delà d'une profondeur , ce que font les bibliothèques standard.
4. Pourquoi on l'emploie quand même. À nombre de comparaisons comparable — contre pour la fusion à —, le tri rapide gagne sur trois points que le comptage ne montre pas :
- il trie en place, sans le tampon de ;
- sa partition parcourt le tableau séquentiellement, ce que la mémoire cache du processeur récompense ;
- ses constantes sont plus petites : un échange contre une recopie dans un tampon puis un retour.
La complexité asymptotique départage les algorithmes ; elle ne les classe pas. Le tri par partition-fusion garde l'avantage quand la garantie compte plus que la moyenne, quand les données sont sur disque — la fusion lit séquentiellement, la partition non — et quand la stabilité est requise.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.