Vous êtes sur la page 1sur 79

1 de 46

Algorithmique

Trouver et Trier
Florent Hivert
Ml : Florent.Hivert@lri.fr
Page personnelle : http://www.lri.fr/hivert

2 de 46

Algorithmes et structures de donnes

La plupart des bons algorithmes fonctionnent grce une mthode


astucieuse pour organiser les donnes. Par exemple, on sait trs
bien, intuitivement, que pour retrouver une carte dans un jeu, il est
trs utile que le jeu soit tri.
Trouver et Trier :
Donald E. Knuth, The Art of Computer Programming
(TAOCP), Volume 3 : Sorting and Searching, Addison-Wesley,
1998.

2 de 46

Algorithmes et structures de donnes

La plupart des bons algorithmes fonctionnent grce une mthode


astucieuse pour organiser les donnes. Par exemple, on sait trs
bien, intuitivement, que pour retrouver une carte dans un jeu, il est
trs utile que le jeu soit tri.
Trouver et Trier :
Donald E. Knuth, The Art of Computer Programming
(TAOCP), Volume 3 : Sorting and Searching, Addison-Wesley,
1998.

Recherche dans un tableau, dichotomie

Recherche dans un
tableau, dichotomie

3 de 46

Recherche dans un tableau, dichotomie

4 de 46

Algorithme de recherche dun lment dans un tableau

Algorithme
Entre : un tableau tab de taille taille et un lment e.
Sortie : i tel que tab[i] = e ou NonTrouv (ex : 1).
pour i de 0 taille-1 faire
si tab[i] = e alors
retourner i
retourner NonTrouv
Complexit : O(taille) (1).

Recherche dans un tableau, dichotomie

5 de 46

Recherche dun lment dans un tableau


La complexit prcdente est trop leve, surtout sachant que la
recherche dans un tableau est une opration de base utilise dans
de nombreux algorithmes.
Pour aller plus vite, on peut utiliser les tableaux tris et la
dichotomie (mthode diviser pour rgner) :

Retenir (Ide)
Si le tableau tab est tri, pour tout indice i,
les lments e tab[i] sont dindice i ;
les lments e > tab[i] sont dindice > i.
On essaye avec i au milieu du tableau.

Recherche dans un tableau, dichotomie

6 de 46

Recherche dichotomique
Algorithme (RechDichoRec : recherche dans un tableau tri)
Entre : un tableau tri tab, un intervalle [min, max] avec
0 min max < taille et un lment e.
Sortie : i tel que tab[i] = e ou NonTrouv (ex : 1).
si min = max alors
si tab[min] = e alors retourner min
sinon
retourner NonTrouv
mid <- (min + max) / 2
si tab[mid] < e alors
retourner RechDichoRec(tab, mid+1, max, e)
sinon
retourner RechDichoRec(tab, min, mid, e)
Complexit : (log2 (taille)).

Recherche dans un tableau, dichotomie

7 de 46

Recherche dichotomique itrative


Remarque : La recherche dichotomique est rcursive terminale.

Algorithme (RechDichoIt recherche dichotomique itrative)


min <- 0;
max <- taille - 1
tant que min < max faire
mid <- (min + max) / 2
si tab[mid] < e alors
min <- mid+1
sinon
max <- mid
si tab[min] = e alors retourner min
sinon
retourner NonTrouv
Complexit : (log2 (taille)).

Recherche dans un tableau, dichotomie

8 de 46

On peut stopper la recherche plus tt si lon a trouv !


Algorithme (Recherche dichotomique variante)
min <- 0;
max <- taille - 1
tant que min < max faire
mid <- (min + max) / 2
si tab[mid] = e alors retourner mid
sinon si tab[mid] < e alors
min <- mid+1
sinon
max <- mid-1
si tab[min] = e alors retourner min
sinon
retourner NonTrouv
Complexit : O(log2 (taille)) (1).

Recherche dans un tableau, dichotomie

9 de 46

Autre application de la recherche dichotomique


Jeu du nombre inconnu o lon rpond soit plus grand soit
plus petit soit gagn.
Calcul dune racine dune fonction croissante (exemple :

x).

Algorithme de pointage, de vise.


Recherche de lapparition dun bug dans lhistorique dun
programme (commandes hg bisect, git-bisect. . .)
Exemple : 100 modifications, 10 minutes de tests pour chaque
modifications. Lalgorithme naif demande 1000 min16h40 au
lieu de 70min1h10 par dichotomie.

Tableaux tris, algorithmes de tris

Tableaux tris,
algorithmes de tris

10 de 46

Tableaux tris, algorithmes de tris

Insertion dans un tableau tri


Algorithme (Insert)
Entres :
Tableau tab, max_taille lments allous
lments 0 i < taille < max_taille initialiss.
un lment e.

Prcondition : tab est tri (tab[i] tab[i + 1]).


Effet : e ajout tab tri.
i <- taille
tant que i > 0 et tab[i-1] > e faire
tab[i] <- tab[i-1]
i <- i-1
tab[i] <- e
taille <- taille + 1
Complexit : O(taille)

11 de 46

Tableaux tris, algorithmes de tris

12 de 46

Tri par insertion


Algorithme (InsertSort)
Entre : Tableau T de taille taille.
Effet : T tri.
pour i de 1 taille-1 faire
e <- t[i]
// Insrer e sa place dans T[0], ..., T[i-1]
j <- i
tant que j > 0 et T[j-1] > e faire
t[j] <- t[j-1]
j <- j-1
T[j] <- e
Complexit : O(taille2 )

Algorithmes plus efficaces : Diviser pour rgner

Algorithmes plus efficaces :


Diviser pour rgner

13 de 46

Algorithmes plus efficaces : Diviser pour rgner

14 de 46

Diviser pour rgner

Du latin Divide ut imperes (Machiavel)


On divise un problme de grande taille en plusieurs (deux)
sous-problmes analogues. Diffrentes stratgies :
1

rcursivit sur les donnes : on spare les donnes en deux


parties arbitraires, puis on rsout les sous-problmes, pour
enfin combiner les rsultats.

rcursivit sur le rsultat : on effectue un pr-traitement


pour bien dcouper les donnes, afin que, aprs avoir rsolu les
sous-problmes, les sous-rsultats se combinent deux-mmes.

Algorithmes plus efficaces : Diviser pour rgner

14 de 46

Diviser pour rgner

Du latin Divide ut imperes (Machiavel)


On divise un problme de grande taille en plusieurs (deux)
sous-problmes analogues. Diffrentes stratgies :
1

rcursivit sur les donnes : on spare les donnes en deux


parties arbitraires, puis on rsout les sous-problmes, pour
enfin combiner les rsultats.

rcursivit sur le rsultat : on effectue un pr-traitement


pour bien dcouper les donnes, afin que, aprs avoir rsolu les
sous-problmes, les sous-rsultats se combinent deux-mmes.

Algorithmes plus efficaces : Diviser pour rgner

15 de 46

Rcursivit sur les donnes :


On spare les donnes en deux parties arbitraires, puis on rsout les
sous-problmes, pour enfin combiner les rsultats.

Comment obtenir un tableau tri, si lon sait


trier chaque moiti ?

Fusion de tableaux tri !

Algorithmes plus efficaces : Diviser pour rgner

15 de 46

Rcursivit sur les donnes :


On spare les donnes en deux parties arbitraires, puis on rsout les
sous-problmes, pour enfin combiner les rsultats.

Comment obtenir un tableau tri, si lon sait


trier chaque moiti ?

Fusion de tableaux tri !

Algorithmes plus efficaces : Diviser pour rgner

15 de 46

Rcursivit sur les donnes :


On spare les donnes en deux parties arbitraires, puis on rsout les
sous-problmes, pour enfin combiner les rsultats.

Comment obtenir un tableau tri, si lon sait


trier chaque moiti ?

Fusion de tableaux tri !

Algorithmes plus efficaces : Diviser pour rgner

Fusion de deux tableaux tris


Algorithme (Fusion de tableaux trie)
Entre : Tableaux T1, T2 tris de taille t1, t2,
Tableau T allou de taille t = t1 + t2
Sortie : T avec les contenus T1 et T2 tri
i1 <- 0; i2 <- 0; i <- 0
tant que i1 < t1 et i2 < t2 faire
si T1[i1] < T2[i2] alors
T[i] <- T1[i1]; i++; i1++
sinon
T[i] <- T2[i2]; i++; i2++
si i1 < t1 alors
tant que i1 < t1 faire
T[i] <- T1[i1]; i++; i1++
sinon
tant que i2 < t2 faire
T[i] <- T2[i2]; i++; i2++
Complexit : (t)

16 de 46

Algorithmes plus efficaces : Diviser pour rgner

Tri par fusion (MergeSort)


Algorithme (TriFusion)
Entre : Tableaux T de taille t, 0 min max < t
Tableau Tmp allou de taille t
Sortie : T tri.
si min <> max alors
mid <- (min+max) / 2
TriFusion(T, min, mid)
TriFusion(T, mid+1, max)
Fusion(T[min..mid], T[mid+1..max], Tmp)
Copie de Tmp dans T[min..max]
Complexit : (t log(t))

17 de 46

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

18 de 46

Complexit du tri par Fusion (1)


Pour simplifier, on suppose que la taille du tableau est une
puissance de 2.
On note ck = dn le nombre de copies dlments si T est de taille
n = 2k . On trouve
c0 = d1 = 0
c1 = d2 = 2 + 2 (fusion + copie)
c2 = d4 = 2c1 + 4 + 4 = 16 (rec + fusion + copie)
c3 = d8 = 2c2 + 8 + 8 = 48 (rec + fusion + copie)
c4 = d16 = 2c3 + 16 + 16 = 128 (rec + fusion + copie)
c5 = d32 = 2c4 + 32 + 32 = 320 (rec + fusion + copie)
c6 = d64 = 2c5 + 64 + 64 = 768 (rec + fusion + copie)
c7 = d128 = 2c6 + 128 + 128 = 1792 (rec + fusion + copie)

Algorithmes plus efficaces : Diviser pour rgner

19 de 46

Complexit du tri par fusion (2)


Proposition
Le nombre ck de copies dlments effectues par le tri par fusion
dun tableau de n = 2k lments vrifie :
c0 = 0

et

ck = 2(ck1 + 2k ) .

ck = 2k+1 k = 2n log2 (n) .


Preuve par rcurrence :
vrai pour k = 0
si ck = 2k+1 k alors
ck+1 = 2(ck + 2k+1 ) = 2(2k+1 k + 2k+1 ) = 2k+2 (k + 1)

Algorithmes plus efficaces : Diviser pour rgner

19 de 46

Complexit du tri par fusion (2)


Proposition
Le nombre ck de copies dlments effectues par le tri par fusion
dun tableau de n = 2k lments vrifie :
c0 = 0

et

ck = 2(ck1 + 2k ) .

ck = 2k+1 k = 2n log2 (n) .


Preuve par rcurrence :
vrai pour k = 0
si ck = 2k+1 k alors
ck+1 = 2(ck + 2k+1 ) = 2(2k+1 k + 2k+1 ) = 2k+2 (k + 1)

Algorithmes plus efficaces : Diviser pour rgner

19 de 46

Complexit du tri par fusion (2)


Proposition
Le nombre ck de copies dlments effectues par le tri par fusion
dun tableau de n = 2k lments vrifie :
c0 = 0

et

ck = 2(ck1 + 2k ) .

ck = 2k+1 k = 2n log2 (n) .


Preuve par rcurrence :
vrai pour k = 0
si ck = 2k+1 k alors
ck+1 = 2(ck + 2k+1 ) = 2(2k+1 k + 2k+1 ) = 2k+2 (k + 1)

Algorithmes plus efficaces : Diviser pour rgner

20 de 46

Complexit du tri par fusion (3)


appels rcursifs

cot niveau
=

O(n)

+
n
2

n
2

O(n)

+
n
22

n
22

n
22

n
22

O(n)

+
..
.
n
2k

..
.

..
.

n
2k

..
.

k
X
i =0

..
.

2i

n
2i

..
.

..
.
n
2k

k
X
i =0

..
.
+

n
2k

..
.

O(n)

..
.
+

O(k n)

O(n log n)

Algorithmes plus efficaces : Diviser pour rgner

21 de 46

Tri par fusion / insertion


Nombre de copie dlments (cas le pire) :
k
n
insert
fusion

0
1
0
0

1 2 3
4
5
6
... k
2 4 8 16 32
64 . . . 2k
3 12 42 150 558 2142 . . . (n+1)(n+2)
3
2
4 16 48 128 320 768 . . . 2k+1 k

Retenir
Pour les petites valeurs de n, le tri par fusion fait plus de copies que
le tri par insertion.
De plus, les appels rcursifs induise des cots supplmentaires. . .

Algorithmes plus efficaces : Diviser pour rgner

21 de 46

Tri par fusion / insertion


Nombre de copie dlments (cas le pire) :
k
n
insert
fusion

0
1
0
0

1 2 3
4
5
6
... k
2 4 8 16 32
64 . . . 2k
3 12 42 150 558 2142 . . . (n1)(n+4)
2
4 16 48 128 320 768 . . . 2k+1 k

Retenir
Pour les petites valeurs de n, le tri par fusion fait plus de copies que
le tri par insertion.
De plus, les appels rcursifs induise des cots supplmentaires. . .

Algorithmes plus efficaces : Diviser pour rgner

21 de 46

Tri par fusion / insertion


Nombre de copie dlments (cas le pire) :
k
n
insert
fusion

0
1
0
0

1 2 3
4
5
6
... k
2 4 8 16 32
64 . . . 2k
3 12 42 150 558 2142 . . .
4 16 48 128 320 768 . . . 2k+1 k

Retenir
Pour les petites valeurs de n, le tri par fusion fait plus de copies que
le tri par insertion.
De plus, les appels rcursifs induise des cots supplmentaires. . .

Algorithmes plus efficaces : Diviser pour rgner

22 de 46

Tri par fusion / insertion

Retenir (Tri mixte fusion / insertion)


Pour des petits tableaux le tri par insertion est plus rapide. Il vaut
mieux lutiliser comme cas de base de la rcursion :
si max - min < SEUIL alors
InsertSort(T[min..max])
sinon
mid <- (min+max) / 2
TriFusion(T, min, mid)
TriFusion(T, mid+1, max)
Fusion(T[min..mid], T[mid+1..max], Tmp)
Copie de Tmp dans T

La valeur de SEUIL est dtermin exprimentalement.

Algorithmes plus efficaces : Diviser pour rgner

23 de 46

Le tri par fusion nest pas en place

On utilise un tableau de taille t supplmentaire (en fait en tant


astucieux, un tableau de taille 2t suffit).

Dfinition
On dit quun tri est en place, sil utilise un emplacement mmoire
constant (O(1)) en plus du tableau pour stocker ses lments.
Les tris par bulles et insertions sont en place ;
Le tri par fusion nest pas en place.
On aimerait bien avoir un tri en n log(n) en place. . .

Algorithmes plus efficaces : Diviser pour rgner

23 de 46

Le tri par fusion nest pas en place

On utilise un tableau de taille t supplmentaire (en fait en tant


astucieux, un tableau de taille 2t suffit).

Dfinition
On dit quun tri est en place, sil utilise un emplacement mmoire
constant (O(1)) en plus du tableau pour stocker ses lments.
Les tris par bulles et insertions sont en place ;
Le tri par fusion nest pas en place.
On aimerait bien avoir un tri en n log(n) en place. . .

Algorithmes plus efficaces : Diviser pour rgner

23 de 46

Le tri par fusion nest pas en place

On utilise un tableau de taille t supplmentaire (en fait en tant


astucieux, un tableau de taille 2t suffit).

Dfinition
On dit quun tri est en place, sil utilise un emplacement mmoire
constant (O(1)) en plus du tableau pour stocker ses lments.
Les tris par bulles et insertions sont en place ;
Le tri par fusion nest pas en place.
On aimerait bien avoir un tri en n log(n) en place. . .

Algorithmes plus efficaces : Diviser pour rgner

23 de 46

Le tri par fusion nest pas en place

On utilise un tableau de taille t supplmentaire (en fait en tant


astucieux, un tableau de taille 2t suffit).

Dfinition
On dit quun tri est en place, sil utilise un emplacement mmoire
constant (O(1)) en plus du tableau pour stocker ses lments.
Les tris par bulles et insertions sont en place ;
Le tri par fusion nest pas en place.
On aimerait bien avoir un tri en n log(n) en place. . .

Algorithmes plus efficaces : Diviser pour rgner

24 de 46

Rcursivit sur le rsultat


On effectue un pr-traitement pour bien dcouper les donnes, puis
rsoudre les sous-problmes, pour que les sous-rsultats se
combinent deux-mmes la fin.

Comment sparer les lements dun tableau


en deux pour que si lon trie chaque partie le
rsultat soit trie ?

Partition dun tableau !

Algorithmes plus efficaces : Diviser pour rgner

24 de 46

Rcursivit sur le rsultat


On effectue un pr-traitement pour bien dcouper les donnes, puis
rsoudre les sous-problmes, pour que les sous-rsultats se
combinent deux-mmes la fin.

Comment sparer les lements dun tableau


en deux pour que si lon trie chaque partie le
rsultat soit trie ?

Partition dun tableau !

Algorithmes plus efficaces : Diviser pour rgner

25 de 46

Problme de partition dun ensemble


Retenir
Soit un ensemble E et un prdicat P(e) sur les lements de E :
Alors
et
PE PE =
E = PE PE
o
PE := {e E | P(e) est vrai }
PE := {e E | P(e) est faux }
On dit que (PE , PE ) est une partition de E .
Exemple : E = {1, 2, . . . 10}, P(e) = e est pair.

Algorithmes plus efficaces : Diviser pour rgner

Partition et tris

Pour obtenir un algorithme de tri on peut :


1

effectuer une partition du tableau en plaant les petits


lments au dbut et les grands la fin.

trier chacune des parties indpendemment.

Tri rapide (QuickSort) !

26 de 46

Algorithmes plus efficaces : Diviser pour rgner

Partition et tris

Pour obtenir un algorithme de tri on peut :


1

effectuer une partition du tableau en plaant les petits


lments au dbut et les grands la fin.

trier chacune des parties indpendemment.

Tri rapide (QuickSort) !

26 de 46

Algorithmes plus efficaces : Diviser pour rgner

Partition et tris

Pour obtenir un algorithme de tri on peut :


1

effectuer une partition du tableau en plaant les petits


lments au dbut et les grands la fin.

trier chacune des parties indpendemment.

Tri rapide (QuickSort) !

26 de 46

Algorithmes plus efficaces : Diviser pour rgner

27 de 46

Partition dun tableau (1)

Algorithme (PartitionnerPredicat)
Entre : Tableaux tab[taille], prdicat P sur les lments
de tab.
Sortie : entier 0 c < taille
Effet : change les lments de telle sorte que :
les lements du tableau qui vrifient P sont dans
tab[0] . . . tab[c 1] ;
les lements du tableau qui ne vrifient pas P sont dans
tab[c] . . . tab[taille 1].

Algorithmes plus efficaces : Diviser pour rgner

28 de 46

Partition dun tableau (2)


0

c
P(e) vrai

n1

j
P(e) faux

Algorithme (PartitionnerPredicat)
c <- 0
tant que c < taille et P(tab[c]) faire
c <- c + 1
pour j de c+1 taille-1 faire
si P(tab[j]) alors
changer tab[c] et tab[j]
c <- c+1
retourner c
Complexit : (taille).

Algorithmes plus efficaces : Diviser pour rgner

28 de 46

Partition dun tableau (2)


0

c
P(e) vrai

n1

j
P(e) faux

Algorithme (PartitionnerPredicat)
c <- 0
tant que c < taille et P(tab[c]) faire
c <- c + 1
pour j de c+1 taille-1 faire
si P(tab[j]) alors
changer tab[c] et tab[j]
c <- c+1
retourner c
Complexit : (taille).

Algorithmes plus efficaces : Diviser pour rgner

29 de 46

Partition dun tableau (2 bis)

PartitionnerPredicat fait beaucoup de dplacement dlments.


0

c
P(e) vrai

n1

j
P(e) faux

En particulier dans certains cas dgnrs, il effectue taille


change l o un seul est ncessaire.
Par exemple, si P(tab[0]) est faux, mais P(tab[i]) est vrai pour
tous les i > 0 alors PartitionnerPredicat dcale tout le tableau
alors quil suffirait dchanger le premier avec le dernier lment.

Algorithmes plus efficaces : Diviser pour rgner

30 de 46

Partition dun tableau (variante)


0

i
P(e) vrai

j
?

n1
P(e) faux

Algorithme (PartitionnerPredicatDeux)
i <- 0
j <- taille-1
tant que i < j faire
tant que P(tab[i]) faire i <- i+1
tant que non P(tab[j]) faire j <- j-1
si i < j alors
changer tab[j] avec tab[j]
i <- i+1; j <- j-1
retourner i

Algorithmes plus efficaces : Diviser pour rgner

30 de 46

Partition dun tableau (variante)


0

i
P(e) vrai

j
?

n1
P(e) faux

Algorithme (PartitionnerPredicatDeux)
i <- 0
j <- taille-1
tant que i < j faire
tant que P(tab[i]) faire i <- i+1
tant que non P(tab[j]) faire j <- j-1
si i < j alors
changer tab[j] avec tab[j]
i <- i+1; j <- j-1
retourner i

Algorithmes plus efficaces : Diviser pour rgner

30 de 46

Partition dun tableau (variante)


0

i
P(e) vrai

j
?

n1
P(e) faux

Algorithme (PartitionnerPredicatDeux FAUX)


i <- 0
j <- taille-1
tant que i < j faire
tant que P(tab[i]) faire i <- i+1
tant que non P(tab[j]) faire j <- j-1
si i < j alors
changer tab[j] avec tab[j]
i <- i+1; j <- j-1
retourner i

Algorithmes plus efficaces : Diviser pour rgner

Partition dun tableau (variante)


Attention ! Lalgorithme PartitionnerPredicatDeux ne
marche pas si tous ou aucun des lments ne vrifient le
prdicat P.
En effet, si tous les lments vrifient le prdicat, la ligne
tant que P(tab[i]) faire i <- i+1
sort du tableau.
Inversement, si aucun des lments ne vrifie le prdicat,
tant que non P(tab[j]) faire j <- j-1
sort du tableau.

Comment corriger lalgorithme ?

31 de 46

Algorithmes plus efficaces : Diviser pour rgner

Partition dun tableau (variante)


Attention ! Lalgorithme PartitionnerPredicatDeux ne
marche pas si tous ou aucun des lments ne vrifient le
prdicat P.
En effet, si tous les lments vrifient le prdicat, la ligne
tant que P(tab[i]) faire i <- i+1
sort du tableau.
Inversement, si aucun des lments ne vrifie le prdicat,
tant que non P(tab[j]) faire j <- j-1
sort du tableau.

Comment corriger lalgorithme ?

31 de 46

Algorithmes plus efficaces : Diviser pour rgner

Partition dun tableau (variante)


Attention ! Lalgorithme PartitionnerPredicatDeux ne
marche pas si tous ou aucun des lments ne vrifient le
prdicat P.
En effet, si tous les lments vrifient le prdicat, la ligne
tant que P(tab[i]) faire i <- i+1
sort du tableau.
Inversement, si aucun des lments ne vrifie le prdicat,
tant que non P(tab[j]) faire j <- j-1
sort du tableau.

Comment corriger lalgorithme ?

31 de 46

Algorithmes plus efficaces : Diviser pour rgner

Partition dun tableau (variante)


Algorithme (PartitionnerPredicatDeux)
i <- 0
j <- taille-1
tant que i < taille et P(tab[i]) faire i <- i+1
tant que j >= 0 et non P(tab[j]) faire j <- j-1
tant que i < j faire
tant que P(tab[i]) faire i <- i+1
tant que non P(tab[j]) faire j <- j-1
si i < j alors
changer tab[j] avec tab[j]
i <- i+1; j <- j-1
retourner i

32 de 46

Partition dun tableau avec pivot

Partition dun tableau


avec pivot

33 de 46

Partition dun tableau avec pivot

34 de 46

Adaptation du partitionnement au tri rapide

Algorithme (Spcification de PartitionnerPivot)


Entre : un tableau tab, un intervalle [min, max] avec
0 min max < taille
Effet : le tableau est rordonn de sorte que pour un certain
min c max, on ait
si min i < c alors tab[i] tab[c] ;
si c < i max alors tab[i] tab[c].

min
ep
Sortie : la position c du pivot

c
p

max
ep

Partition dun tableau avec pivot

Adaptation du partitionnement au tri rapide


Algorithme (PartitionnerPivot)
Entre : un tableau tab, un intervalle [min, max]
Sortie : la position du pivot
pivot <- tab[max]
c <- min
tant que tab[c] < pivot faire c <- c+1
pour j de c+1 max-1 faire
si tab[j] < pivot alors
changer tab[c] et tab[j]
c <- c+1
changer tab[c] et tab[max]
retourner c

35 de 46

Partition dun tableau avec pivot

36 de 46

Partition dun tableau avec pivot (variante)


min
i
e pivot

j
?

max 1 max
e pivot pivot

Algorithme (PartitionnerPivotDeux)
pivot <- tab[max]
i <- min; j <- max-1
repeter
tant que tab[i] < pivot faire i <- i+1
tant que tab[j] > pivot faire j <- j-1
si i < j alors
changer tab[i] avec tab[j]
i <- i+1; j <- j-1
sinon
changer tab[i] avec tab[max]
retourner i

Partition dun tableau avec pivot

36 de 46

Partition dun tableau avec pivot (variante)


min
i
e pivot

j
?

max 1 max
e pivot pivot

Algorithme (PartitionnerPivotDeux)
pivot <- tab[max]
i <- min; j <- max-1
repeter
tant que tab[i] < pivot faire i <- i+1
tant que tab[j] > pivot faire j <- j-1
si i < j alors
changer tab[i] avec tab[j]
i <- i+1; j <- j-1
sinon
changer tab[i] avec tab[max]
retourner i

Le tri rapide

37 de 46

Le tri rapide

Le tri rapide

38 de 46

Algorithme du tri rapide


Charles Antony Richard HOARE 1961.
0
ep

n1
ep

Retenir (Ide)
choisir un lment p appel pivot ;
placer gauche les lments infrieur p ;
placer droite les lments suprieur p ;
trier rcursivement la partie de droite et celle de gauche.

Le tri rapide

39 de 46

Complexit du QuickSort
Retenir
La complexit du partitionnement dun tableau de taille n est (n).
Dans le cas le pire, cest--dire
si le pivot est le plus grand lment et donc est plac la fin
aprs le partitionnement,
ou si le pivot est le plus petit lment et donc est plac au
dbut aprs le partitionnement,

Retenir
Dans le cas le pire, la complexit du QuickSort est (n2 ).

Le tri rapide

39 de 46

Complexit du QuickSort
Retenir
La complexit du partitionnement dun tableau de taille n est (n).
Dans le cas le pire, cest--dire
si le pivot est le plus grand lment et donc est plac la fin
aprs le partitionnement,
ou si le pivot est le plus petit lment et donc est plac au
dbut aprs le partitionnement,

Retenir
Dans le cas le pire, la complexit du QuickSort est (n2 ).

Le tri rapide

39 de 46

Complexit du QuickSort
Retenir
La complexit du partitionnement dun tableau de taille n est (n).
Dans le cas le pire, cest--dire
si le pivot est le plus grand lment et donc est plac la fin
aprs le partitionnement,
ou si le pivot est le plus petit lment et donc est plac au
dbut aprs le partitionnement,

Retenir
Dans le cas le pire, la complexit du QuickSort est (n2 ).

Le tri rapide

Influence du choix du pivot

Retenir
Pour avoir des bonnes performances dans QuickSort, il est
important que le pivot soit bien choisi.
En pratique, sur une permutation au hasard, le pivot coupe le
tableau peu prs en deux :

Retenir
En moyenne, le QuickSort une complexit de (n log(n)).

40 de 46

Le tri rapide

Influence du choix du pivot

Retenir
Pour avoir des bonnes performances dans QuickSort, il est
important que le pivot soit bien choisi.
En pratique, sur une permutation au hasard, le pivot coupe le
tableau peu prs en deux :

Retenir
En moyenne, le QuickSort une complexit de (n log(n)).

40 de 46

Le tri rapide

Influence du choix du pivot

Retenir
Pour avoir des bonnes performances dans QuickSort, il est
important que le pivot soit bien choisi.
En pratique, sur une permutation au hasard, le pivot coupe le
tableau peu prs en deux :

Retenir
En moyenne, le QuickSort une complexit de (n log(n)).

40 de 46

Le tri rapide

41 de 46

Influence du choix du pivot, en pratique

Retenir
Pour avoir des bonnes performances dans QuickSort, il est
important que le pivot soit bien choisi.
Plusieurs stratgies sont proposes :
choisir un lment au milieu du tableau ;
choisir un lment au hasard dans le tableau ;
choisir la mdiane du premier, de celui du milieu et du dernier.

Le tri rapide

42 de 46

Bilan
Avantages du QuickSort :
en place, avec une petite utilisation de pile pour les appels
rcursifs. ;
bonne complexit en moyenne n log(n) ;
boucle intrieur trs courte ;
trs bien compris thoriquement.
Dsavantages du QuickSort :
rcursif, difficile implanter dans les environnements o la
rcursion nest pas possible ;
mauvaise complexit dans le cas le pire n2 ;
fragile : beaucoup de possibilit pour faire une erreur subtile en
limplantant.

Peut-on faire mieux que O(n log(n)) ?

Peut-on faire mieux


que O(n log(n)) ?

43 de 46

Peut-on faire mieux que O(n log(n)) ?

44 de 46

La complexit O(n log(n)) est optimale !

Thorme
Pour tout algorithme de tri fonctionnant en comparant les donnes
la complexit dans le cas le pire est (n log(n)) (au moins n log(n)).
Preuve : Arbres de dcision binaire + formule de Stirling.

Peut-on faire mieux que O(n log(n)) ?

45 de 46

Arbre de dcision binaire

a<b
a<c

b<c
a<c

abc
acb

b<c

bac
cab

bca

cba

Proposition
La profondeur de larbre est au moins dlog2 (n)e o n est le nombre
de feuille.

Peut-on faire mieux que O(n log(n)) ?

Permutations et formule de Stirling

Il y a n! manires de permuter un tableaux de n nombres.


James Stirling (16921770) :

 n n 

1
1
139
+
n! = 2n
1+
+
+
e
12n 188n2 51840n3

On en dduit
log(n!) = n log(n) n + O(n)

46 de 46

Peut-on faire mieux que O(n log(n)) ?

Permutations et formule de Stirling

Il y a n! manires de permuter un tableaux de n nombres.


James Stirling (16921770) :

 n n 

1
1
139
+
n! = 2n
1+
+
+
e
12n 188n2 51840n3

On en dduit
log(n!) = n log(n) n + O(n)

46 de 46

Peut-on faire mieux que O(n log(n)) ?

Permutations et formule de Stirling

Il y a n! manires de permuter un tableaux de n nombres.


James Stirling (16921770) :

 n n 

1
1
139
+
n! = 2n
1+
+
+
e
12n 188n2 51840n3

On en dduit
log(n!) = n log(n) n + O(n)

46 de 46

Vous aimerez peut-être aussi