Vous êtes sur la page 1sur 5

Exercice corrigé

Complexité en moyenne du MergeSort et du QuickSort

Exercice 1. On rappelle que les complexités en pire cas de l’algorithme de tri-fusion ( MergeSort, J. von
Neumann 1945) et de l’algorithme de tri rapide ( QuickSort, C.A.R. Hoare 1960) sont respectivement en
O(n log n) et en O(n2 ) (tableau déjà trié). Montrer que leurs complexités en moyenne sont en O(n log n).

Démonstration. MergeSort : l’algorithme peut s’écrire en pseudo-langage :

procedure MergeSort(premier,dernier : entiers) est


si premier < dernier alors
milieu : entier := (premier+dernier)/2;
MergeSort(premier,milieu); -- trie T[premier..milieu]
MergeSort(milieu+1,dernier); -- trie T[milieu+1..dernier]
Fusion(premier,milieu,dernier);
fin si;
fin procedure;
avec
procedure Fusion(premier,milieu,dernier : entiers) est
-- Indices de parcours des sous-tableaux :
i : entier := premier;
j : entier := milieu+1;
-- Tableau auxiliaire et indice de parcours :
Tprime : entier[premier..dernier];
k : entier := premier;

tant que (i <= milieu) ou (j <= dernier) faire


si (i > milieu) alors
Tprime[k] := T[j];
j := j+1;
sinon
si (j > dernier) alors
Tprime[k] := T[i];
i := i+1;
sinon -- ni i ni j ne sont encore au bout
si (T[i] < T[j]) alors
Tprime[k] := T[i];
i := i+1;
sinon
Tprime[k] := T[j];
j := j+1;
fin si;
fin si;
fin si;
k := k+1;
fin tant que;
T[premier..dernier] := Tprime[premier..dernier];
fin procedure;

Grenoble-INP Ensimag, 1ère année, 2010-2011 Algo 2 — Exercice corrigé


Notons n le nombre d’éléments du tableau : n = dernier − premier + 1. Dans la procédure Fusion(),
il y a exactement n + 1 comparaisons entre éléments du tableau, car i ou j (forcément l’un des deux,
mais uniquement l’un des deux) est incrémenté à chaque tour de la boucle tant que. Notons Cmoy (n) la
complexité en moyenne de l’algorithme MergeSort pour un tableau à n éléments. D’après l’écriture de la
procédure MergeSort() ci-dessus, et puisque le coût de la fusion est n + 1, on a trivialement
n n
Cmoy (n) = Cmoy (b c) + Cmoy (d e) + n + 1.
2 2
En supposant que n est une puissance de deux (sinon, on peut faire un encadrement : 2i ≤ n < 2i+1 ), on
obtient l’équation de récurrence suivante :
n
Cmoy (n) = 2Cmoy ( ) + n + 1. (1)
2
n
On obtient, en remplaçant n par 2 dans cette équation,
n n n
Cmoy ( ) = 2Cmoy ( ) + + 1.
2 4 2
et donc
n n
Cmoy (n) = 4Cmoy ( ) + 2( + 1) + n + 1.
4 2
En poursuivant le même raisonnement, on obtient, pour tout k ≤ 1,
k
n X n
Cmoy (n) = 2k Cmoy ( k
) + 2i ( i + 1).
2 i=0
2
n
On s’arrête bien sûr quand 2k
= 1, soit k = log n :

log
Xn n
Cmoy (n) = nCmoy (1) + 2i ( + 1).
i=0
2i

La complexité moyenne pour un tableau à un élément est constante. Notons c sa valeur (peu importe ce que
vaut c). On a donc
log
Xn
Cmoy (n) = cn + n(log n + 1) + 2i .
i=0

On connaı̂t l’expression exacte de la série géométrique :

2log n+1 − 1
Cmoy (n) = (c + 1)n + n log n + .
2−1
On obtient donc finalement

Cmoy (n) = (c + 1)n + n log n + 2n − 1 = n log n + (c + 3)n − 1.

Le terme prépondérant asymptotiquement est bien évidemment le n log n, et on a donc :

Cmoy (n) = O(n log n) (2)

Grenoble-INP Ensimag, 1ère année, 2010-2011 Algo 2 — Exercice corrigé


QuickSort : l’algorithme peut s’écrire en pseudo-langage :

procedure QuickSort(premier,dernier : entiers) est


si premier < dernier alors
pivot : entier := premier; -- par exemple
pivot := Partition(premier,dernier,pivot);
QuickSort(premier,pivot-1);
QuickSort(pivot+1,dernier);
fin si;
fin procedure;
avec
fonction Partition(premier, dernier, pivot : entiers) retourne entier est
-- Indices de parcours des sous-tableaux :
i : entier := premier+1;
j : entier := dernier;

Echange(T[premier],T[pivot]);
tant que i <= j faire
tant que (i <= j et T[i] < T[premier]) faire
-- on avance i jusqu’à ^
etre sur un élément plus grand que T[premier]
i := i+1;
fin tant que;
tant que (i <= j et T[j] > T[premier]) faire
-- on recule j jusqu’à ^etre sur un élément plus petit que T[premier]
j := j-1;
fin tant que;
si i < j alors
Echange(T[i],T[j]);
i := i+1;
j := j-1;
fin si;
-- on arr^ete quand i et j se croisent
fin tant que;
Echange(T[premier],T[j]);
-- T[1..j-1] et T[j+1..dernier] contiennent respectivement
-- les valeurs inférieures et supérieures à T[j]
retourner j;
fin fonction;
Notons n le nombre d’éléments du tableau : n = dernier − premier + 1. Dans la fonction Partition(), il y
a exactement n + 1 comparaisons entre un élément du tableau et T [premier], car on teste toutes les valeurs
de i et de j exactement une fois jusqu’à ce que i et j se croisent. La procédure QuickSort() étant récursive,
sa complexité en moyenne peut donc s’écrire :

Cmoy (n) = n + 1 + moyenne1≤pivot≤n (Cmoy (pivot − 1) + Cmoy (n − pivot)).

En effet Cmoy (pivot − 1) représente la complexité en moyenne de l’appel QuickSort(premier,pivot-1), et


Cmoy (n − pivot) celle de l’appel QuickSort(premier,pivot-1).
Faisons maintenant une hypothèse d’équiprobabilité : supposons que la procédure Partition() renvoie

Grenoble-INP Ensimag, 1ère année, 2010-2011 Algo 2 — Exercice corrigé


de manière équiprobable n’importe quelle valeur entre premier et dernier. Comme on a n valeurs, chaque
valeur a une probabilité n1 d’être renvoyée. La moyenne s’écrit donc :
n
1X
moyenne1≤pivot≤n (Cmoy (pivot − 1) + Cmoy (n − pivot)) = (Cmoy (p − 1) + Cmoy (n − p)).
n p=1

On a donc finalement l’équation de récurrence suivante :


n
1X
Cmoy (n) = n − 1 + (Cmoy (p − 1) + Cmoy (n − p)), (3)
n p=1

avec les conditions initiales :


Cmoy (1) = Cmoy (0) = 1.
La fin de la démonstration n’est que du calcul ! Afin d’éliminer la somme de l’équation, on peut changer de
variable pour la seconde moitié de la somme et réécrire :
n n
1X 1X
Cmoy (n) = n + 1 + Cmoy (p − 1) + Cmoy (q − 1)
n p=1 n q=1

d’où
n
2X
Cmoy (n) = n + 1 + Cmoy (p − 1)
n p=1
ou encore
n
X
nCmoy (n) = n(n + 1) + 2 Cmoy (p − 1), (4)
p=1

et donc
n−1
X
(n − 1)Cmoy (n − 1) = (n − 1)n + 2 Cmoy (p − 1). (5)
p=1

La soustraction des équations (4) et (5) donne :

nCmoy (n) − (n − 1)Cmoy (n − 1) = n((n + 1) − (n − 1)) + 2Cmoy (n − 1),

d’où
nCmoy (n) = 2n + (n + 1)Cmoy (n − 1),
ou encore en divisant par n(n + 1) :
Cmoy (n) Cmoy (n − 1) 2
= + . (6)
n+1 n n+1
Cette nouvelle équation de récurrence est beaucoup plus simple car on n’a plus de somme, et on peut en
déduire :
Cmoy (n − 1) Cmoy (n − 2) 2
= + . (7)
n n−1 n
On a donc, en combinant les équations (6) et (7) :
Cmoy (n) Cmoy (n − 2) 2 2
= + + .
n+1 n−1 n+1 n
En continuant ainsi, on obtient
n+1
Cmoy (n) Cmoy (1) X 2
= + ,
n+1 2 k
k=3

Grenoble-INP Ensimag, 1ère année, 2010-2011 Algo 2 — Exercice corrigé


c’est-à-dire
n+1
Cmoy (n) 5 X2
=− + .
n+1 2 k
k=1
n
X 1
Comme ∼n→+∞ log n, on en déduit
k
k=1

Cmoy (n)∼n→+∞ 2n log n (8)

Remarque. Même si dans le pire cas le QuickSort est asymptotiquement plus coûteux en temps de cal-
cul que le MergeSort (O(n2 ) contre O(n log n)), on remarque qu’en moyenne les deux algorithmes ont un
comportement similaire (tout ceci, bien sûr, sous de bonnes conditions d’équiprobabilité). En pratique, on
constate même que le QuickSort est au moins 2 fois plus rapide que le MergeSort (voir notamment [1]). Ceci
est du au coût d’opérations autres que les comparaisons entre éléments de tableau, par exemple la recopie de
tableau du MergeSort. Les étudiants intéressés ou voulant s’exercer au calcul de complexités sont fortement
incités à se référer à [2].

Remarque. L’équation 1 est classique pour un algorithme qui applique le principe “Diviser pour Régner”.
Sa résolution l’est également. Nous y reviendrons à la fin du semestre.

Bibliographie indicative
[1] R. Sedgewick. Algorithmes en langage C : cours et exercices. Dunod, 2000.
[2] R. Sedgewick, P. Flajolet. Introduction à l’analyse des algorithmes. International Thomson Publishing
Company, 1996.
[1] est disponible à la B.U. Sciences et à la bibliothèque MI2S. [2] est disponible à la B.U. Sciences, et en
anglais à la bibliothèque MI2S.

Grenoble-INP Ensimag, 1ère année, 2010-2011 Algo 2 — Exercice corrigé

Vous aimerez peut-être aussi