0% ont trouvé ce document utile (0 vote)
167 vues72 pages

Tri et Algorithmes : Cours INF411

Le document décrit plusieurs algorithmes de tri, notamment le tri par insertion, le tri fusion et la preuve qu'aucun algorithme de tri ne peut être plus efficace que O(N log N) dans le pire des cas.

Transféré par

Daniel Ramos
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
167 vues72 pages

Tri et Algorithmes : Cours INF411

Le document décrit plusieurs algorithmes de tri, notamment le tri par insertion, le tri fusion et la preuve qu'aucun algorithme de tri ne peut être plus efficace que O(N log N) dans le pire des cas.

Transféré par

Daniel Ramos
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Ecole

Polytechnique
INF411

Les bases de la programmation


et de lalgorithmique
Jean-Christophe Filliatre
Bloc 6 / lundi 3 octobre 2016

motivation

quels sont les dix mots les plus frequents dans


Le tour du monde en quatre-vingts jours ?

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

une solution en une ligne


on peut le faire avec le shell, en une ligne !
cat file | tr -cs [:alpha:] [\n*] | sort | uniq -c | sort -rn

2826
1616
1587
1472
1112
952
832
788
766
670
...

de
le
la
et
il
les
un
en
du
Fogg

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

explication
on envoie le fichier sur la sortie standard
cat ltdme80j.txt
on remplace les caract`eres non-alphabetiques par un retour-charriot
| tr -cs [:alpha:] [\n*]
on trie les lignes par ordre alphabetique
| sort
on regroupe les lignes identiques, en les comptant (-c)
| uniq -c
on trie numeriquement (-n), en ordre inverse (-r)
| sort -rn

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

tri

on a utilise ici deux tris


un tri par ordre alphab
etique (de 76 420 lignes)
un tri num
erique (de 8 608 lignes)

lobjet de lamphi daujourdhui est justement le tri

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

melanger

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

melanger

comment melanger N valeurs correctement ?

par exemple les N elements dun tableau

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

le melange de Knuth (Knuth shuffle)


chaque element i est echange avec un element j [0, i]
static<E> void shuffle(E[] a) {
for (int i = 1; i < a.length; i++) {
int j = (int)(Math.random() * (i + 1)); // j dans 0..i
swap(a, i, j);
}
}
0
1
1
1
1
1
Jean-Christophe Filli
atre

1
0
0
3
3
3

2
2
2
2
2
2

3
3
3
0
0
5

4
4
4
4
4
4

INF411

5
5
5
5
5
0

j=0
j=2
j=1
j=4
j=3

X2015 / bloc 6

bon melange
for (int i = 1; i < a.length; i++) {
int j = (int)(Math.random() * (i + 1)); // j dans 0..i
swap(a, i, j);
}
avant

x0

x1

x2

...

xn1

apr`es

y0

y1

y2

...

yn1

montrons que la probabilite que yk = xl apr`es letape i vaut


Pi (yk = xl ) =

1
i +1

pour 0 k, l i

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

preuve
par recurrence sur i
clair pour i = 0
supposons le r
esultat pour i 1

avant

x0

x1

...

xi1

xi

apr`es

y0

y1

...

yi1

yi

pour k = i
Pi (yi = xi ) =
l < i,

Pi (yi = xl ) =

1
i +1
X
0j<i

X
0j<i

Jean-Christophe Filli
atre

(pas dechange)
1
Pi1 (yj = xl )
i +1
1
1

i +1
i

1
i +1

INF411

X2015 / bloc 6

10

preuve
par recurrence sur i
clair pour i = 0
supposons le r
esultat pour i 1

avant

x0

x1

...

xi1

xi

apr`es

y0

y1

...

yi1

yi

pour k < i
Pi (yk = xi ) =
l < i,

Pi (yk = xl ) =
=
=

1
(echange)
i +1
i
Pi1 (yk = xl )
i +1
1
i

i +1
i
1
i +1


Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

11

le melange de Knuth

est facile `
a ecrire
de complexit
e O(N)
donne chacune des N! permutations avec la m
eme probabilite

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

12

complexite du probl`eme du tri

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

13

optimalite

`a quelle vitesse peut-on esperer trier ?

dit autrement : quelle est la meilleure complexite dans le pire des cas ?

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

14

hypoth`ese

on suppose que lalgorithme


ne proc`
ede que par comparaisons entre elements
ne poss`
ede aucune information quant `a la distribution

le co
ut sera justement le nombre de comparaisons effectuees

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

15

exemple
on peut trier trois valeurs a, b, c ainsi

a < b?
b<c?
abc

b<c?

a<c?
acb

cab

a<c?
bac

cba

bca

(un tel arbre, appele questionnaire, represente lalgorithme)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

16

cout

ici, on fait 2 ou 3 comparaisons selon lentree


donc 3 comparaisons dans le pire des cas

on se persuade facilement que cest optimal pour N = 3 :


on ne peut trier trois valeurs avec au plus deux comparaisons

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

17

de mani`ere generale
un algorithme qui trie N valeurs peut etre vu comme un arbre binaire
o`
u chaque nud est un test et chaque feuille une permutation

il y a au moins N! feuilles
la complexit
e dans le pire des cas est la hauteur de cet arbre

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

18

minoration

N! nombre de feuilles 2hauteur


donc
hauteur log2 (N!) =

log2 (i) N log2 (N)

1iN

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

19

complexite du probl`eme du tri

aucun algorithme, procedant par comparaisons uniquement,


ne peut trier N valeurs en effectuant toujours moins que
N log N
comparaisons

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

20

en particulier

le tri par tas, vu la semaine derni`ere, est optimal

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

21

cas particuliers

bien entendu, on peut faire mieux quand on poss`ede une information


supplementaire sur les elements

exemple : si les N elements ne prennent que deux valeurs distinctes,


alors on peut trier en O(N)

(cf exercices 82, 83 et 84 du poly)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

22

tri par insertion

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

23

tri par insertion

le plus naturel : on ins`ere successivement chaque nouvel element


parmi les elements dej`a tries

0
i-1 i
. . . dej`a trie . . . v

Jean-Christophe Filli
atre

INF411

. . . `a trier . . .

X2015 / bloc 6

24

code
static void insertionSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int v = a[i], j = i;
// on d
ecale les
el
ements vers la droite
for (; 0 < j && v < a[j-1]; j--) a[j] = a[j-1];
// jusqu`
a avoir trouv
e la place j de v
a[j] = v;
}
}
v
j

Jean-Christophe Filli
atre

. . . `a trier . . .

INF411

X2015 / bloc 6

25

questionnaire pour N = 4
a

a < b?
b<c?

a<c?

c <d?
abcd

a<c?

b<d?
abdc

b<d?

a<d?
adbc

acbd

dabc

b<d?

c <d?
acdb

c <d?

cabd

a<d?
adcb

dacb

bacd

a<d?
cadb

a<d?
badc

c <d?
cdab

b<c?

dcab

a<d?

b<d?
bdac

dbac

bcad

a<d?

c <d?
bcda

cbad

cbda

b<d?
bdca

b<d?

dbca

c <d?
cdba

dcba

(hauteur 6 > dlog(24)e)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

26

complexite

dans le pire des cas, linsertion de a[i] demande i comparaisons (tableau


trie en ordre inverse), do`
u un total
1 + 2 + + N 1

N2
2

dans le meilleur des cas, linsertion de a[i] demande une seule


comparaison (le tableau est dej`a trie), do`
u un total
N

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

27

complexite

comparaisons
affectations

meilleur cas
N
N

moyenne
N 2 /4
N 2 /4

pire cas
N 2 /2
N 2 /2

+ lineaire sur un tableau dej`a trie


quadratique dans le pire des cas
N = 105 plusieurs milliards doperations

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

28

tri fusion

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

29

diviser pour regner

1. couper le tableau en deux moities egales


2. les trier recursivement
3. fusionner les resultats

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

30

tri fusion (mergesort)


il faut generaliser au tri de a[l..r[
1. couper le tableau en deux moities egales m = b l+r
2 c
l

a
2. trier recursivement a[l..m[ et a[m..r[
l
m
a
trie
trie

3. fusionner les resultats


l

r
trie

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

31

exemple
2 5 3 8 5 1 4
2 5 3

8 5 1 4

5 3
2

3
3 5
2 3 5

8 5
8

1 4
5

5 8

1 4

1 4 5 8

1 2 3 4 5 5 8
Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

32

difficulte

il est extremement difficile de realiser la fusion en place


on va utiliser un second tableau

static void mergesort(int[] a) {


mergesortrec(a, new int[a.length], 0, a.length);
}

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

33

code
trier a[l..r[ en utilisant le tableau auxiliaire tmp
static void mergesortrec(int[] a, int[] tmp, int l, int r){
if (l >= r-1) return; // au plus un
el
ement
int m = l + (r - l) / 2;
mergesortrec(a, tmp, l, m);
mergesortrec(a, tmp, m, r);
for (int i = l; i < r; i++) tmp[i] = a[i];
merge(tmp, a, l, m, r);
}
(note : (l + r) / 2 pourrait provoquer un debordement arithmetique)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

34

fusion
fusionne a1[l..m[ et a1[m..r[ dans a2[l..r[
static void merge(int[] a1, int[] a2, int l, int m, int r){
int i = l, j = m;
for (int k = l; k < r; k++)
if (i < m && (j == r || a1[i] <= a1[j]))
a2[k] = a1[i++];
else
a2[k] = a1[j++];
}
l
a1

a2

m
trie
i

r
trie
j

trie
k

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

35

questionnaire pour N = 4

a < b?
c <d?

c <d?

a<c?

a<d?

b<c?
abcd

a<d?

b<d?
acbd

acdb

b<d?
cabd

cdab

cadb

b<c?

b<d?
abdc

a<c?

b<c?
adbc

adcb

b<c?
dabc

b<d?

a<c?

dcab

bacd

dacb

b<d?

a<d?
bcad

bcda

a<d?
cbad

cbda

cdba

a<d?
badc

b<c?

a<c?
bdac

bdca

a<c?
dbac

dcba

dbca

(hauteur 5 = dlog(24)e)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

36

complexite

soit CN le nombre de comparaisons pour trier N elements


on a

C0 = C1 = 0
C =C N +C N +f
N
N
b c
d e
2

o`
u fN est le co
ut de la fusion

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

37

complexite
supposons le pire des cas (fN = N) et N = 2n pour simplifier les calculs
il vient
C2n

= C2n1 + C2n1 + 2n

C2n
2n

C2n1
+1
2n1

C2n2
+1+1
2n2

= n
cest-`a-dire
CN = N log2 (N)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

38

complexite

comparaisons
affectations

meilleur cas
1
2 N log N
2N log N

moyenne
N log N
2N log N

pire cas
N log N
2N log N

+ complexite optimale
espace supplementaire O(N)
+ sapplique facilement aux listes, en place
(cf TD de cette semaine)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

39

taille de pile

les appels recursifs imbriques occupent de lespace sur la pile (cf amphi 1)
mais cet espace est en O(log N),
car |r l| est divise par deux `a chaque fois

donc on ne provoquera pas StackOverflowError

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

40

optimisations

quand r l devient tr`


es petit, faire un tri par insertion
pas besoin de fusionner si a[m-1] a[m]

(devient alors lineaire sur un tableau dej`a trie)


pour
eviter la copie dans tmp,

echanger le role des deux tableaux `a chaque fois


(cf exercice 79 du poly)
on peut sarr
eter d`es que le segment est dej`a trie (natural mergesort)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

41

variantes

on a procede de haut en bas (top-down mergesort)

on peut aussi proceder de bas en haut (bottom-up mergesort)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

42

tri rapide

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

43

question

comment eviter lespace auxiliaire


tout en conservant le principe diviser pour regner ?

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

44

tri rapide (quicksort)


on conserve lidee de trier a[l..r[

1. r
earranger les elements pour avoir
l
a
<p

r
p

pour une certaine valeur p appelee pivot

2. trier r
ecursivement a[l..m[ et a[m..r[
l
m
a
trie
trie

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

45

exemple

2 5 3 8 5 1 4
1 2 5 3 8 5 4

5 3 8 5 4
3 4 5 8 5
3 4
3 4
4

Jean-Christophe Filli
atre

INF411

8 5
5 8
5

X2015 / bloc 6

46

code
static void quicksort(int[] a) {
quickrec(a, 0, a.length);
}
static void quickrec(int[] a, int l, int r) {
if (l >= r-1) return; // au plus un
el
ement
int m = partition(a, l, r);
quickrec(a, l,
m);
l
m
quickrec(a, m + 1, r);
<p
p
}

r
p

il ne reste plus qu`a ecrire partition

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

47

partition
on choisit arbitrairement a[l] comme pivot
l
p

i
p

<p

r
?

static int partition(int[] a, int l, int r) {


int p = a[l], m = l;
for (int i = l + 1; i < r; i++)
if (a[i] < p)
swap(a, i, ++m);
swap(a, l, m);
return m;
}
l
<p
Jean-Christophe Filli
atre

m
p
INF411

r
p
X2015 / bloc 6

48

complexite

soit CN le nombre de comparaisons pour trier N elements

C0 = C1 = 0

CN = N
1} + CK + CN1K

| {z
|{z}

| {z }

partition

`
a gauche

`
a droite

pour un tableau dej`a trie, K = 0


CN = N 1 + CN1

Jean-Christophe Filli
atre

INF411

N2
2

X2015 / bloc 6

49

complexite
en moyenne, cependant, cest optimal (preuve dans le poly)

comparaisons
affectations

meilleur cas
N log N
0

moyenne
2N log N
2N log N

pire cas
N 2 /2
N2

meilleur cas comparaisons = pivot au milieu


meilleur cas affectations = pivot `a gauche = pire cas comparaisons
+ en place
pire cas O(N 2 )

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

50

eviter le pire cas

le pire cas correspond `a un pivot au bord

idee : prendre comme pivot un element de a[l..r[ au hasard


encore plus simple : m
elanger avant de trier !
static void quicksort(int[] a) {
KnuthShuffle.shuffle(a);
quickrec(a, 0, a.length);
}

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

51

eviter le pire cas


ne suffit cependant pas si beaucoup delements egaux
(tous les elements egaux pivot forcement au bord)

solution : partitionner en trois (3-way partition)


l

m
<p

{z

puis trier

n
=p

r
>p

{z

puis trier

(cf exercices 76 et 83 dans le poly)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

52

taille de pile

comme pour le tri fusion,


les appels recursifs imbriques occupent de lespace sur la pile

mais ici cet espace peut etre en O(N)


(on ne decoupe plus systematiquement en deux moities egales)
provoque alors StackOverflowError !

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

53

solution

on peut
faire un appel r
ecursif sur la plus petite des deux moities
remplacer lautre appel r
ecursif par une boucle while

on retrouve alors une taille de pile en O(log N)

(cf exercice 77 du poly)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

54

autre optimisation

quand r l devient tr`


es petit, faire un tri par insertion

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

55

tri par tas

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

56

tri par tas (cf amphi 5)


static void moveDown(int[] a, int i, int x, int n) {
while (true) {
int j = 2 * i + 1;
if (j >= n) break;
if (j + 1 < n && a[j] < a[j + 1]) j++;
if (a[j] <= x) break;
a[i] = a[j]; i = j;
}
a 8 3 7 1 2 4 3
a[i] = x;
8
}
static void heapsort(int[] a) {
3
7
int n = a.length;
for (int k = n / 2 - 1; k >= 0; k--)
moveDown(a, k, a[k], n);
1
2
4
3
for (int k = n - 1; k >= 1; k--) {
int v = a[k]; a[k] = a[0];
moveDown(a, 0, v, k);
}
}
Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

57

complexite

le tri par tas est en O(N log N) dans le pire des cas
(cf amphi 5)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

58

pourquoi tous ces tris ?

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

59

pourquoi tous ces tris ?

ils ont chacun des avantages et des inconvenients

en place ou non
efficace sur un tableau (presque) d
ej`a trie
optimal dans le pire des cas
stable

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

60

stabilite

Definition
Un tri est stable sil preserve lordre dapparition des elements egaux.

non significatif pour des elements de type int


mais de mani`ere generale on trie des objets dun type E quelconque
class Sort<E extends Comparable<E>> { ... }
static<E extends Comparable<E>> void sort(E[] a) { ... }

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

61

exemple

un ensemble de films est donne par ordre chronologique


on trie selon la note moyenne des commentaires, avec un tri stable
r
esultat : `a note egale, les films restent tries par ordre chronologique

(cest une facon dobtenir un ordre lexicographique)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

62

comparaison

insertion
fusion
rapide
par tas

moyenne
O(N 2 )
O(N log N)
O(N log N)
O(N log N)

pire cas
O(N 2 )
O(N log N)
O(N 2 )
O(N log N)

dej`a trie
O(N)
O(N)
O(N 2 )
O(N log N)

en place
oui
non
oui
oui

stable
oui
oui
non
non

et les constantes cachees dans les O peuvent faire une difference

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

63

la biblioth`eque Java
fournit un grand nombre de methodes Arrays.sort(...)
tri rapide pour les types primitifs

void sort( char[] a);


void sort(
int[] a);
void sort(double[] a);
...

tri fusion pour les objets

void sort(T[] a); // si T impl


emente Comparable<T>
void sort(T[] a, Comparator<T> c);
garanti stable
Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

64

applications

le tri ne sert pas qu`a organiser des donnees

cest aussi un ingredient de base de nombreux algorithmes

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

65

exemple : calcul de lenveloppe convexe


entree = N points dans le plan
sortie = points formant lenveloppe convexe

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

66

algorithme de Graham
1 determiner le point p le plus bas
2 trier tous les points selon langle fait avec p

3 considerer les points dans cet ordre,


en les ajoutant/retirant de lenveloppe convexe
d
emo
Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

67

complexite

letape 1 est clairement en O(N)


letape 2 est en O(N log N) (tri de N valeurs)
letape 3 est O(N), car chaque point est ajoute une fois dans lenveloppe,
retire au plus une fois de lenveloppe

cest donc une solution en O(N log N)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

68

optimalite
on ne peut pas faire mieux
en effet, soient N entiers x1 , . . . , xN
trouver lenveloppe convexe des N points (xi , xi2 ) revient `a les trier

et on a vu que le tri ne peut etre fait en moins de N log N


Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

69

lecon

quand on programme, il faut faire des petits dessins !

l
p

Jean-Christophe Filli
atre

m
<p

i
p

INF411

r
?

X2015 / bloc 6

70

le TD de cette semaine

le tri fusion de listes, en place

application : une autre facon de trouver les mots les plus frequents
Le tour du monde
`a `a `a `a
`a(1678) ah(4) bien(13)
de(2826) `a(1678) le(1616) la(1499)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

71

la semaine prochaine

lire le poly, chapitre 13. Tri

il y a des exercices dans le poly

bloc 7 : graphes (1/2)

Jean-Christophe Filli
atre

INF411

X2015 / bloc 6

72

Vous aimerez peut-être aussi