Probleme – Le tri par partition-fusion, et la troisième récurrence
Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 5 — Récursivité
Énoncé
- Écrire en OCaml le tri par partition-fusion sur les listes : une fonction
coupequi sépare, une fonctionfusionqui recolle, et le tri lui-même. - Prouver la terminaison, puis la correction de
fusionpar récurrence. - Résoudre à la main, sans théorème général.
- Comparer le nombre mesuré de comparaisons à , qui minore le coût de tout tri par comparaisons.
Corrigé
1. Le tri.
(* coupe l renvoie deux listes dont la reunion est l, de longueurs
egales a une unite pres. Complexite : Theta(|l|). *)
let rec coupe = function
| [] -> ([], [])
| [x] -> ([x], [])
| x :: y :: r -> let (a, b) = coupe r in (x :: a, y :: b)
(* fusion a b : si a et b sont triees, renvoie la liste triee de leurs
elements reunis (avec repetitions). Complexite : Theta(|a| + |b|). *)
let rec fusion a b = match a, b with
| [], l | l, [] -> l
| x :: r, y :: s -> if x <= y then x :: fusion r b else y :: fusion a s
(* tri l renvoie la liste des elements de l, triee par ordre croissant. *)
let rec tri = function
| ([] | [_]) as l -> l
| l -> let (a, b) = coupe l in fusion (tri a) (tri b)
Vérification : coupe [3;1;4;1;5;9;2;6] rend ([3;4;5;2], [1;1;9;6]) — un élément sur deux — et tri [3;1;4;1;5;9;2;6] rend [1;1;2;3;4;5;6;9] en comparaisons.
2. Les preuves.
Terminaison de tri. Variant : la longueur de la liste. Le cas récursif ne se produit que si , et coupe rend alors deux listes de longueurs et , toutes deux strictement inférieures à — c'est là que la garde est indispensable : pour , coupe rendrait et le variant ne décroîtrait pas.
Correction de fusion, par récurrence forte sur . Si l'une des listes est vide, l'autre est triée et contient exactement les éléments à rendre. Sinon, et ; supposons . Comme est triée, minore ; comme est triée et , minore aussi . Donc est un minimum de la réunion, et le placer en tête est correct pourvu que la suite le soit : c'est l'hypothèse de récurrence appliquée à , dont la somme des longueurs a diminué de . Le cas est symétrique.
Correction de tri, par récurrence forte sur : les deux moitiés sont triées par hypothèse, et fusion rend alors la réunion triée.
3. La récurrence, résolue à la main. Poser . Le coût vérifie avec . On déroule niveau par niveau : au niveau , il y a appels portant chacun sur éléments, et la fusion de chacun coûte . Le coût du niveau vaut donc
indépendamment de . Il y a niveaux avant d'atteindre les listes à un élément, d'où
C'est le calcul que la figure du cours fait en empilant des rectangles de même aire, et c'est tout ce qu'il faut : aucun théorème-maître.
4. La confrontation à la borne inférieure. Un tri par comparaisons doit distinguer les permutations possibles ; chaque comparaison rend un bit ; il en faut donc au moins . Mesuré, sur des listes aléatoires :
n : 10 100 1000 10000 100000
comparaisons : 24 550 8743 120396 1536335
n log2 n : 33 664 9966 132877 1660964
log2(n!) : 22 525 8529 118458 1516704
Le tri par partition-fusion fait de comparaisons de plus que le minimum absolu à . Il n'est pas seulement d'ordre optimal : il est presque optimal en constante. C'est ce qui explique sa place centrale, et le chapitre chap:diviser y reviendra pour montrer que la même récurrence gouverne toute une famille d'algorithmes.
Une réserve honnête. Sur les listes, coupe et fusion allouent maillons par niveau, soit allocations au total, et la version présentée de fusion n'est pas terminale — donc en pile. Sur un tableau, le même tri se fait avec un seul tampon auxiliaire de taille .
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.