0% ont trouvé ce document utile (0 vote)
23 vues77 pages

Conception Des Algorithmes Introduction

Le document présente des stratégies de conception d'algorithmes, notamment la programmation dynamique, les algorithmes gloutons et la méthode 'diviser pour régner'. Il illustre ces concepts à travers des exemples tels que le dégroupage optimal de la bande passante et la multiplication optimale d'une chaîne de matrices. Le cours s'inspire de références académiques sur les algorithmes et les structures de données.

Transféré par

mohamed.ghraieb
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)
23 vues77 pages

Conception Des Algorithmes Introduction

Le document présente des stratégies de conception d'algorithmes, notamment la programmation dynamique, les algorithmes gloutons et la méthode 'diviser pour régner'. Il illustre ces concepts à travers des exemples tels que le dégroupage optimal de la bande passante et la multiplication optimale d'une chaîne de matrices. Le cours s'inspire de références académiques sur les algorithmes et les structures de données.

Transféré par

mohamed.ghraieb
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

Conception des algorithmes

Hicham Bensaid

Département RIM

Hicham Bensaid (Département RIM) Conception des algorithmes 1 / 77


Introduction

En première partie, nous avons traité les notions suivantes :


Algorithmes,
algorithmique et
structures de données.
⇒ analyser des algorithmes existants.
Dans cette partie nous allons apprendre certaines stratégies de
conception des algorithmes.
Le cours est largement fondé sur (et inspiré de) les livres :
Fundamentals of Algorithmics, G. Brassard and P. Bratley
Introduction to Algorithms, Third Edition, T. H. Cormen, C. E.
Leiserson, R. L. Rivest and C. Stein

Hicham Bensaid (Département RIM) Conception des algorithmes 2 / 77


Plan

1 Motivations

2 Programmation dynamique
Dégroupage optimal
Multiplication optimale d’une chaine de matrices

3 Algorithmes gloutons

4 Diviser pour régner


Tri par fusion
Tri rapide (quicksort)

Hicham Bensaid (Département RIM) Conception des algorithmes 3 / 77


Motivations

Plan

1 Motivations

2 Programmation dynamique
Dégroupage optimal
Multiplication optimale d’une chaine de matrices

3 Algorithmes gloutons

4 Diviser pour régner


Tri par fusion
Tri rapide (quicksort)

Hicham Bensaid (Département RIM) Conception des algorithmes 4 / 77


Motivations

Stratégies

Nous allons aborder 3 techniques importantes de conception des


algorithmes :
Programmation dynamique
Algorithmes gloutons
Diviser pour régner
Nous avons déjà vu (en première partie) d’autres techniques :
Approche incrémentale (tri par insertion)
Exploitation des propriétés des S.D.
Récurrence

Hicham Bensaid (Département RIM) Conception des algorithmes 5 / 77


Motivations

Exemple introductif
Terme général de la suite de Fibonacci :
(
n si n ∈ {0, 1}
Fn =
F n−1 + F n−2 si n ≥ 2

Implémentation récursive 4
simple
w '
Mais complexité 3 2

exponentielle  
2 1 1 0

La cause : les mêmes 


calculs répétés plusieurs 1 0

fois
Nous allons voir comment faire de manière plus efficace (et plus
intelligente)

Hicham Bensaid (Département RIM) Conception des algorithmes 6 / 77


Programmation dynamique

Plan

1 Motivations

2 Programmation dynamique
Dégroupage optimal
Multiplication optimale d’une chaine de matrices

3 Algorithmes gloutons

4 Diviser pour régner


Tri par fusion
Tri rapide (quicksort)

Hicham Bensaid (Département RIM) Conception des algorithmes 7 / 77


Programmation dynamique

Programmation dynamique

Résout les problèmes en combinant les solutions des sous problèmes


(un peu comme diviser pour régner)
Utile quand les sous problèmes chevauchent (contrairement à DpR)
Utile quand on peut exhiber une structure de sous problèmes optimaux
La programmation dynamique résout chaque problème 1 seule fois et
stocke le résultat pour d’autre usages (d’où l’intérêt du
chevauchement)
Utile dans les problèmes d’optimisation (mais pas que, cf. suite de
Fibonacci)

Hicham Bensaid (Département RIM) Conception des algorithmes 8 / 77


Programmation dynamique

Étapes de la programmation dynamique

1 Caractériser la structure d’une solution optimale


2 Définir récursivement la valeur d’une solution optimale
3 Calculer la valeur d’une solution optimale
4 Construire une solution optimale à partir de la valeur (info) calculée

Hicham Bensaid (Département RIM) Conception des algorithmes 9 / 77


Programmation dynamique

Programmation dynamique à travers l’exemple

Nous allons étudier cette technique à travers deux exemples :


Problème du dégroupage optimal de la bande passante
Problème de multiplication optimale de plusieurs matrices

Hicham Bensaid (Département RIM) Conception des algorithmes 10 / 77


Programmation dynamique Dégroupage optimal

Premier exemple : dégroupage optimal de la bande passante

Une bande passante d’un opérateur à partager avec un ou plusieurs


concurrents
En dégroupant, chaque “morceau” de bande passante a un prix de
session
Comment maximiser le gain (la somme des prix) après dégroupage ?

largeur B.P. i 1 2 3 4 5 6 7 8 9 10
prix p i 1 5 8 9 10 17 17 20 24 30

Hicham Bensaid (Département RIM) Conception des algorithmes 11 / 77


Programmation dynamique Dégroupage optimal

Dégroupage optimal

Exemple : bande passante de largeur = 4

La solution optimale dans ce cas est de partager en 2 sous-bandes de


largeurs identiques = 2
Le gain maximal = 5 + 5 = 10
Le problème : algorithme pour résoudre le problème (et non pas l’instance)

Hicham Bensaid (Département RIM) Conception des algorithmes 12 / 77


Programmation dynamique Dégroupage optimal

Dégroupage optimal

1ère solution (naïve) : énumérer tous les dégroupages possibles


Problème : complexité exponentielle. Il y a 2n−1 dégroupages possibles
(il existe 2n−1 applications de l’ensemble {0, 1} (couper / ne pas couper)
dans l’ensemble {1, 2, . . . , n − 1})
Sinon ... on analyse le problème
caractériser
¡
la solution optimale : ¢
r n = max p n , r 1 + r n−1 , r 2 + r n−2 , . . . , r n−1 + r 1
Problème initial décomposé en plusieurs problèmes similaires mais sur
des instances plus petites
la solution optimale globale utilise des solutions optimales des sous
problèmes définis (solvables indépendamment)
⇒ Le problème de découpe optimale présente une sous structure
optimale
¡ ¢
r n peut être encore simplifiée : r n = max p i + r n−i

Hicham Bensaid (Département RIM) Conception des algorithmes 13 / 77


Programmation dynamique Dégroupage optimal

Solution récursive
¡ ¢
La formule r n = max p i + r n−i suggère d’utiliser diviser pour régner
(solution récursive)
Entrée : un tableau p et un entier n indiquant la largeur où "couper"
Résultat : le gain maximum
1 function degrouperBPRec(p, n )
2 if n == 0 then
3 return 0
4 q = −∞
5 for i = 1 to n¡ do ¢
6 q = max q, p[i ] + degrouperBPRec(p, n − i )
7 return q
Algorithme 1 : degrouperBPRec
Complexité ?

Hicham Bensaid (Département RIM) Conception des algorithmes 14 / 77


Programmation dynamique Dégroupage optimal

Analyse de la complexité de la solution récursive


On caractérise T (n) le coût de recherche d’une solution optimale sur une
bande passante de largeur n :
Pn−1
T (n) = 1 + i =0 T (i )
Pn−1 Pn−1
T (n) + i =0 T (i ) = 1 + 2. i =0 T (i )

S(n) = 1 + 2.S(n − 1) ⇒ S ′ (n) = 2.S ′ (n − 1)


Pn−1
S ′ (n) = 2n et donc S(n) = 2n − 1 et T (n) + i =0 T (i ) = 2n − 1
Pn−1
donc 2.T (n) =2n (puisque 1 + i =0 T (i ) = T (n))

finalement T (n) = 2n−1

⇒ Complexité exponentielle
Hicham Bensaid (Département RIM) Conception des algorithmes 15 / 77
Programmation dynamique Dégroupage optimal

La programmation dynamique à la rescousse

Le problème avec DpR : on calcule la même chose plusieurs fois :


4
 &
t + 1
3 2 0
 %   
u
2 1 0 1 0 0
   
1 0 0 0

0

Solution : faire en sorte de ne le faire qu’une fois

Hicham Bensaid (Département RIM) Conception des algorithmes 16 / 77


Programmation dynamique Dégroupage optimal

Approches

Approche top-down : utilise la technique de mémoïsation


une fois une valeur calculée, on la mémorise (dans un tableau par
exemple) pour usage ultérieur
⇒ pas besoin de recalculer

Approche bottom-up : repose sur une relation d’ordre sur la taille du


sous problème :
dans l’exemple précédent le calcul de r k nécessite le calcul de tous les
r i tels que i < k
⇒ on calcule r 0 ensuite r 1 puis r 2 puis r 3 , . . .
⇒ notion de tri topologique

Hicham Bensaid (Département RIM) Conception des algorithmes 17 / 77


Programmation dynamique Dégroupage optimal

Version mémoïsée
Entrée : un tableau p et un entier n indiquant la largeur où couper et un
tableau r
Résultat : le gain maximum
1 function degrouperBPMemAux(p, n, r )
2 if r [n] ≥ 0 then
3 return r [n]
4 if n == 0 then
5 q =0
6 else
7 q = −∞
8 for i = 1 to n¡ do ¢
9 q = max q, p[i ] + degrouperBPMemAux(p, n − i , r )
10 r [n] = q
11 return q
Algorithme 2 : degrouperBPMemAux
Hicham Bensaid (Département RIM) Conception des algorithmes 18 / 77
Programmation dynamique Dégroupage optimal

Version mémoïsée

Entrée : un tableau p et un entier n indiquant la largeur de la B. P.


Résultat : le gain maximum
1 function degrouperBPMem(p, n )
2 Soit r [0..n] un nouveau tableau
3 for i = 1 to n do
4 r [i ] = −∞
5 return degrouperBPMemAux(p, n, r )
Algorithme 3 : degrouperBPMem

Complexité en O n 2
¡ ¢

Hicham Bensaid (Département RIM) Conception des algorithmes 19 / 77


Programmation dynamique Dégroupage optimal

Version bottom-up

Entrée : un tableau p et un entier n indiquant la largeur de la bande


Résultat : le gain maximum
1 function degrouperBPBotUp(p, n, r )
2 Soit r [0..n] un nouveau tableau
3 r [0] = 0
4 for j = 1 to n do
5 q = −∞
6 for i = 1 to j¡ do ¢
7 q = max q, p[i ] + r [ j − 1]
8 r [j] = q
9 return r [n]
Algorithme 4 : degrouperBPBotUp

Complexité en O n 2
¡ ¢

Hicham Bensaid (Département RIM) Conception des algorithmes 20 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

Deuxième exemple : multiplication optimale d’une chaine de


matrices

Une chaine de n matrices 〈A 1 , A 2 , . . . , A n 〉 à multiplier et on veut


calculer le produit A 1 A 2 . . . A n
On peut utiliser l’algorithme standard de multiplication de deux
matrices
Il faut choisir un parenthésage pour appliquer l’algorithme
Plusieurs manières de parenthéser (la multiplication de matrices est
associative) conduisant au même résultat
Un produit de matrices est complètement parenthésé ssi
une seule matrice ou
produit de deux matrices complètement parenthésées

Hicham Bensaid (Département RIM) Conception des algorithmes 21 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

Exemple

Chaine à multiplier : 〈A 1 , A 2 , A 3 , A 4 〉
5 manières de parenthéser le produit A 1 A 2 A 3 A 4 :(pourquoi 5 ?,
comment généraliser pour n ?)
(A 1 (A 2 (A 3 A 4 )))
(A 1 ((A 2 A 3 ) A 4 ))
((A 1 A 2 ) (A 3 A 4 ))
((A 1 (A 2 A 3 )) A 4 )
(((A 1 A 2 ) A 3 ) A 4 )
Comment parenthéser peut impacter de manière drastique la
complexité globale du calcul du produit.

Hicham Bensaid (Département RIM) Conception des algorithmes 22 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

Algorithme simple de multiplication de deux matrices

Entrée : deux matrices A et B à multiplier


Résultat : le produit A.B si A et B sont compatibles
1 function produitDeuxMatrices( A, B )
2 Soit C = (ci j ) une nouvelle matrice de taille A.l i g nes × [Link] onnes
3 if [Link] onnes 6= B.l i g nes then
4 error "Matrices incompatibles"
5 else
6 for i = 1 to A.l i g nes do
7 for j = 1 to [Link] onnes do
8 ci j = 0
9 for k = 1 to [Link] onnes do
10 c i j = c i j + (a i k .b k j )

11 return C
Algorithme 5 : produitDeuxMatrices

Temps d’exécution : ≈ n × m × k où n, m, k resp. A.l i g nes , [Link] onnes ,


[Link] onnes
Hicham Bensaid (Département RIM) Conception des algorithmes 23 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

Parenthétisation et complexité

Produit de la chaine 〈A 1 , A 2 , A 3 〉 avec A 1 : 10 × 100, A 2 : 100 × 5, A 3 : 5 × 50


Temps d’exécution :
(A 1 (A 2 A 3 )) : (100 × 5 × 50) + (10 × 100 × 50) = 75000 opérations (à peu
près)
((A 1 A 2 ) A 3 ) : (10 × 100 × 5) + (10 × 5 × 50) = 7500 opérations (à peu près)

On peut aller 10 fois plus vite (ou 10 fois plus lentement) en fonction du
parenthésage ! ! !

Hicham Bensaid (Département RIM) Conception des algorithmes 24 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

Problème de multiplication d’une chaine de matrices

Problème
Etant donnée une chaine de matrices 〈A 1 , A 2 , . . . , A n 〉 où chaque A i est de
dimensions p i −1 × p i , parenthéser complètement le produit A 1 A 2 . . . A n de
manière à minimer le nombre de multiplications scalaires.

Attention
On ne procède pas à une multiplication des matrices mais uniquement
à determiner un parenthésage (ordre de multiplication) qui minimise le
nombre de multiplications scalaires (et donc le temps d’exécution)
Le temps nécessaire pour déterminer le parenthésage est largement
compensé par la réduction du temps de calcul du produit lui même (un
facteur de 10 dans l’exemple)

Hicham Bensaid (Département RIM) Conception des algorithmes 25 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

Première solution (naïve)

Essayer de manière exhaustive toutes les parenthétisations possibles


Problème : solution très inneficace :
P (n) : le nombre
 de parenthétisations possibles d’une chaine de taille n

1 si n = 1
P (n) = n−1
X
 P (k)P (n − k) si n ≥ 2

k=1
On peut démontrer que P (n) = Ω(2n ) (idée : a.b ≥ a + b + 1 et
récurrence)
⇒ solution non satisfaisante

Hicham Bensaid (Département RIM) Conception des algorithmes 26 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

La programmation dynamique à la rescousse

Utiliser la programmation dynamique pour résoudre le problème en utilisant


l’approche en 4 étapes :
1 Caractériser la structure d’une solution optimale
2 Définir la valeur de la solution optimale de manière récursive
3 Calculer la valeur de la solution optimale
4 Construire la solution optimale depuis l’information calculée

Hicham Bensaid (Département RIM) Conception des algorithmes 27 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

1. Structure de la parenthétisation optimale


On doit trouver la sous structure optimale et l’utiliser pour construire
une solution optimale au problème à partir des solutions optimales des
sous problèmes.
Pour notre exemple on note A i .. j où i ≤ j matrice du produit
A i A i +1 . . . A j .
Dans le cas non trivial (i < j ), pour parenthéser A i . . . A j on doit
scinder le produit entre A 1 . . . A k et A k+1 A j pour un i ≤ k < j
C (A 1 . . . A j ) = C (A 1 . . . A k ) +C (A k+1 A j ) + P où P est le coût du produit
entre (A 1 . . . A k ) et (A k+1 A j )
La sous structure optimale est la suivante :
Pour parenthéser (de manière optimale) A i A i +1 . . . A j on scinde le
produite entre A k et A k+1
La parenthétisation de A 1 . . . A k doit être optimale ainsi que celle de
A k+1 A j (sinon on peut trouver une meileure solution ... pourquoi ?)
Il reste à trouver le bon k qui optimise le résultat global.
Hicham Bensaid (Département RIM) Conception des algorithmes 28 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

2. Une solution récursive

m[i , j ] le nombre minimum de multiplications scalaires pour calculer le


produit A i A i +1 . . . A j (m[1, n] est la solution donc au problème global)
si i = j alors m[i , j ] = 0
sinon en supposant connaitre la valeur du bon k
m[i , j ] = m[i , k] + m[k + 1, j ] + p i −1 p k p j
le problème donc est de trouver le bon k

0 si i = j
m[i , j ] = ¡ ¢
 min m[i , k] + m[k + 1, j ] + p i −1 p k p j si i < j
i ≤k< j

m[i , j ] donne le coût de la solution optimale mais ne donne pas la


solution
⇒ on utilise un tableau s[i , j ] pour stocker (en calculant m[i , j ]) le
bon k retenu.
Hicham Bensaid (Département RIM) Conception des algorithmes 29 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

3. Calculs des coûts optimaux

L’implémentation naïve de la formule récursive est exponentielle (vous


pouvez vérifier et voir pourquoi)
En fait le problème vient des chevauchements entre sous problèmes :
le même sous problème peut être rencontré plusieurs fois
une des caractéristiques fondamentales de quand utiliser la
programmation dynamique
On utilise une approche bottom-up (fondée sur un tri topologique)
pour éviter de calculer plusieurs fois la même chose
­ ®
Entrée : une séquence p 0 , p 1 , . . . , p n de taille n + 1 (les tailles des
matrices, on n’a pas besoins des matrices elles mêmes)
La procédure utilise un tableau m[i , j ] pour stocker les coûts et un
tableau s[i , j ] pour les choix des scissions (permet de construire la
solution optimale)

Hicham Bensaid (Département RIM) Conception des algorithmes 30 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

3. Calculs des coûts optimaux - suite

Idée du tri topologique utilisé :


Pour traiter un produit A i . . . A j (i.e. traiter une chaine de j − i + 1)
éléments on a besoin de traiter des sous chaines de tailles < j − i + 1.
Le traitement doit donc aller des plus petites chaines (le cas dégénéré
une chaine réduite à un seul élément) puis les chaines à deux éléments
en allant jusqu’aux chaines ayant le plus d’éléments

Hicham Bensaid (Département RIM) Conception des algorithmes 31 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

3. Calculs des coûts optimaux - L’algorithme (bottom up)


Entrée : une chaine p de tailles de matrices
Résultat : la solution optimale et son coût
1 function produitMatricesTriTopo(p )
2 Soit m[1..n, 1..n] et s[1..n − 1, 2, n] deux tableaux
3 for i = 1 to n do
4 m[i , i ] = 0
5 l représente la taille de la chaine
6 for l = 2 to n do
7 for i = 1 to n − l + 1 do
8 j = i +l −1
9 m[i , j ] = ∞
10 for k = i to j − 1 do
11 q = m[i , k] + m[k + 1, j ] + p i −1 p k p j
12 if q<m[i,j] then
13 m[i , j ] = q
14 s[i , j ] = k

15 return m et s
Algorithme 6 : produitMatricesTriTopo
Hicham Bensaid (Département RIM) Conception des algorithmes 32 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

Exemple

matrice A1 A2 A3 A4 A5 A6
dimension 30 × 35 35 × 15 15 × 5 5 × 10 10 × 20 20 × 25

La solution optimale est donnée par m[1, 6]


Exemple :

m[2, 2] + m[3, 5] + p 1 p 2 p 5 = 13000


m[2, 5] = min m[2, 3] + m[4, 5] + p 1 p 3 p 5 = 7125 = 7125


m[2, 4] + m[5, 5] + p p p = 11375
1 4 5

Hicham Bensaid (Département RIM) Conception des algorithmes 33 / 77


Programmation dynamique Multiplication optimale d’une chaine de matrices

4. Construire une solution optimale


Le tableau m ne donne pas comment parenthéser (il donne uniquement le
nombre d’opérations optimal)
s permet de construire le parenthésage : s[i , j ] = k indique où il faut scinder
entre A i et A j dans le produit A i . . . A k A k+1 A j
En commençant depuis s[1, n] = k on peut construire récursivement en
considérant s[1, k] et s[k + 1, n]
Entrée : un tableau s et deux indices i ≤ j
1 procedure imprimerParenthesageOptimal(s, i , j )
2 if i = j then
3 imprimer " A i "
4 else
5 imprimer "("
6 k = s[i , j ]
7 imprimerParenthesageOptimal(s, i , k )
8 imprimerParenthesageOptimal(s, k + 1, j )

Algorithme 7 : imprimerParenthesageOptimal
L’appel imprimerParenthesageOptimal(s, 1, 6) sur l’exemple précédent
produit le parenthésage : ((A 1 (A 2 A 3 )) ((A 4 A 5 ) A 6 ))
Hicham Bensaid (Département RIM) Conception des algorithmes 34 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

Version top down (memoïsation)


1 function produitMatricesMemoisation(p )
2 n = p.t ai l l e − 1
3 Soit m[1..n, 1..n] un nouveau tableau
4 for i = 1 to n do
5 for j = 1 to n do
6 m[i , j ] = ∞

7 return chercherChaine(m, p, 1, n )
Algorithme 8 : produitMatricesMemoisation
1 function chercherChaine(m, p, i , j )
2 if m[i , j ] < ∞ then
3 return m[i , j ]
4 if i==j then
5 m[i , j ] = 0
6 else
7 for k = i to j − 1 do
8 q =chercherChaine(m, p, i , k ) + chercherChaine(m, p, k + 1, j ) +p i −1 p k p j
9 if q < m[i , j ] then
10 m[i , j ] = q

11 return m[i , j ]
Hicham Bensaid (Département RIM) Conception des algorithmes 35 / 77
Programmation dynamique Multiplication optimale d’une chaine de matrices

Pour résumer

Quand utiliser la programmation dynamique ?


Deux ingrédients pour pouvoir le faire :
sous structure optimale
sous problèmes chevauchants

Hicham Bensaid (Département RIM) Conception des algorithmes 36 / 77


Algorithmes gloutons

Plan

1 Motivations

2 Programmation dynamique
Dégroupage optimal
Multiplication optimale d’une chaine de matrices

3 Algorithmes gloutons

4 Diviser pour régner


Tri par fusion
Tri rapide (quicksort)

Hicham Bensaid (Département RIM) Conception des algorithmes 37 / 77


Algorithmes gloutons

Algorithmes gloutons

Un problème d’optimisation = séquence d’étapes


Dans chaque étape il faut faire un choix parmi plusieurs possibilités
Cela ressemble aux problèmes traités par la programmation dynamique
la programmation dynamique est justement parfois disproportionnée
Un algorithme glouton choisit à chaque étape l’option qui semble la
meilleure parmi celles possibles
Une sorte de suite d’optimisations locales successives vers une
optimisation globale
Exemples : arbre de recouvrement minimal d’un graphe, plus court
chemin dans un graphe acyclique (Dijkstra), codes de Huffman, . . .

Hicham Bensaid (Département RIM) Conception des algorithmes 38 / 77


Algorithmes gloutons

Exemple explicatif : problème de choix de tâches

Problème de planification de plusieurs tâches concurrentes


Une ressource partagée entre toutes les tâches accessible en exclusion
mutuelle
A un instant donnée, une seule tâche peut être active
Objectif : choisir le plus grand nombre de tâches mutuellement
compatibles
S 1 = {a 1 , . . . , a n } ensemble de tâches
Chaque tâche ai a un instant de début s i et de fin f i
£ £
Une tâche est active pendant s i , f i
£ £ £ £
a i et a j sont mutuellement compatibles ssi s i , f i ∩ s j , f j = ;
Hypothèse de simplification : f 1 ≤ f 2 ≤ . . . ≤ f n

Hicham Bensaid (Département RIM) Conception des algorithmes 39 / 77


Algorithmes gloutons

Instance du problème

i 1 2 3 4 5 6 7 8 9 10 11
si 1 3 0 5 3 5 6 8 8 2 12
fi 4 5 6 7 9 9 10 11 12 14 16

{a 3 , a 9 , a 11 } tâches mutuellement compatibles mais non optimale


{a 1 , a 4 , a 8 , a 11 } est plus grande (elle est en fait optimale)
{a 2 , a 4 , a 9 , a 11 } est une autre solution optimale

Hicham Bensaid (Département RIM) Conception des algorithmes 40 / 77


Algorithmes gloutons

Résolution du problème

On va résoudre le problème en plusieurs étapes


1 Essayer de réfléchir à une solution de type programmation dynamique
plusieurs choix pour choisir les sous problèmes de la solution optimale
2 Pour cet exemple, on verra qu’il suffit de considérer un seul choix
le choix glouton
3 Solution récursive du problème
4 Transformation de la solution récursive en itérative

Hicham Bensaid (Département RIM) Conception des algorithmes 41 / 77


Algorithmes gloutons

Sous structure optimale du problème

S i j : ensemble de tâches qui démarrent après la fin de a i et qui se


terminent avant le début de a j
© ª
S i j = ak | f i ≤ sk ≤ f k ≤ s j

On cherche une ensemble maximal A i j de tâches compatibles dans S i j


Soit ak ∈ A i j
A i j = A i k ∪ {a k } ∪ A k j où A i k = A i j ∩ S i k et A k j = A i j ∩ S k j
|A i j | = |A i k | + |A k j | + 1
A i j contient également les solution optimales de S i k et S k j ( A i k et
A k j sont des solutions optimales pour S i k et S k j )

Sinon on aurait A i k ∪ {ak } ∪ A k j solution de S i j et supérieure à A i j

Hicham Bensaid (Département RIM) Conception des algorithmes 42 / 77


Algorithmes gloutons

La programmation dynamique une bonne solution ?

¡ ¢ ¡ ¢
c i , j = c (i , k) + c k, j + 1
Comme on ne connait pas exactement quel ak choisir :

¡ ¢ 0 si S i j = ;
c i, j = © ¡ ¢ ª
 max c (i , k) + c k, j + 1 sinon
a k ∈S i j

Problème solvable en programmation dynamique (algorithme récursif


+ mémoïsation)
Mais . . . est ce qu’on ne peut pas faire mieux ? . . .

Hicham Bensaid (Département RIM) Conception des algorithmes 43 / 77


Algorithmes gloutons

Faire le choix glouton

L’idée pour faire mieux est d’essayer de ne considérer qu’un seul choix
(le choix glouton)
Problème : il faut une condition suffisante pour que le choix glouton
implique une solution optimale
Par exemple, intuitivement si on choisit systématiquement la tâche qui
se termine le plus tôt, on laisse plus de temps pour plus de tâches . . .
Après© le choix glouton,
ª
il reste un seul sous problème :
S k = a i ∈ S|s i ≥ f k (toutes les tâches qui démarrent après la fin de
ak )
La question est : est-ce que l’intuition (choisir la tâche la première à
finir) est correcte ?

Hicham Bensaid (Département RIM) Conception des algorithmes 44 / 77


Algorithmes gloutons

Correction de l’intuition
Théorème
Soient S k 6= ; un sous-problème et am ∈ S k telle que am est la première à terminer (dans
S k ).
a m appartient à un sous-ensemble maximum de tâches de S k mutuellement compatibles

Démonstration.
A k un ensemble maximum solution de S k .
a j ∈ A k est celle qui termine la première
Si a j = a m alors c’est OK (a m ∈ A k )

Sinon, soit A k = A k − {a j } ∪ {a m }

Les tâches de A k sont disjointes : celles de A k le sont et a j est la première à terminer
dans A k et f m ≤ f j

(toutes les autres tâches ai 6= a j de A k démarrent après f j et donc


après f m )
′ ′
|A k | = |A k | et donc A k est maximal

Hicham Bensaid (Département RIM) Conception des algorithmes 45 / 77


Algorithmes gloutons

Algorithme glouton récursif

On choisit la tâche ak qui termine la première


On ne garde que les tâches compatibles avec ak
On répète jusqu’à la fin des tâches
Les instants de fin sont croissants
Une tâche n’est considérée qu’une seule fois

Hicham Bensaid (Département RIM) Conception des algorithmes 46 / 77


Algorithmes gloutons

Algorithme glouton récursif


Entrée : un tableau s des instants de début, un tableau f des instants de
fin, un indice k pour définir le sous-problème S k à résoudre et la
taille n du problème d’origine
Résultat : un sous ensemble de tâches mutuellement compatibles
maximum
1 function tâchesCompatiblesMax( f , s, k, n )
2 m = k +1
3 while m ≤ n and s[m] < f [k] do
4 m = m +1
5 if m ≤ n then
6 return am ∪ tâchesCompatiblesMax( f , s, m, n )
7 else
8 return ;
Algorithme 9 : tâchesCompatiblesMax
On appelle tâchesCompatiblesMax( f , s, 0, n )
Hicham Bensaid (Département RIM) Conception des algorithmes 47 / 77
Algorithmes gloutons

Une autre façon de voir les algorithmes gloutons

Résolution d’un problème de manière optimale. Pour construire la


solution du problème, on a un ensemble (ou liste) C de candidats (les
différentes tâches e.g. )
Lors du déroulement de l’algorithme on accumule deux ensembles :
Un ensemble S des candidats déjà traités et retenus (ils ne seront plus
traités)
Un ensemble X des candidats déjà traités et rejetés (ils ne seront plus
traités)
Il existe une fonction sol ut i on qui vérifie si un ensemble de candidats
fournit une solution au problème (sans tenir compte de l’optimalité)

Hicham Bensaid (Département RIM) Conception des algorithmes 48 / 77


Algorithmes gloutons

Une autre façon de voir les algorithmes gloutons

Une autre fonction f ai sabl e vérifie si un ensemble de candidats peut


être étendu avec un nouvel élément vers une solution
Une fonction de sélection sel ect i on indique à tout moment quel est le
candidat non encore traité le plus prometteur (ça sera le choix glouton)
Enfin une fonction objectif qui donne le résultat trouvé

Hicham Bensaid (Département RIM) Conception des algorithmes 49 / 77


Algorithmes gloutons

Algorithme glouton général itératif


Entrée : un ensemble C
Résultat : un sous-ensemble S de C optimal
1 function gloutonIteratif(C )
2 ; // C est l’ensemble de candidats
3 S =; // Le sous-ensemble solution est construit dans S
4 while C 6= ; and not sol ut i on(S) do
5 x = sel ec t i on(C )
6 C =C −x
7 if f ai sabl e(S ∪ x) then
8 S =S∪x

9 if sol ut i on(S) then


10 return S
11 else
12 return "Pas de solution"
Algorithme 10 : gloutonIteratif
Hicham Bensaid (Département RIM) Conception des algorithmes 50 / 77
Algorithmes gloutons

Application à notre exemple

C = {a 1 , . . . , a n }
¡© ª¢
sol ut i on a i 1 , . . . , a i l = vr ai ssi les a i j mutuellement compatibles et
C = ; (ceci est un cas particulier)
sel ect i on (C ) retourne la première tâche à terminer non encore traitée
¡© ª¢
f ai sabl e a i 1 , . . . , a i l ssi les a i j mutuellement compatibles

Hicham Bensaid (Département RIM) Conception des algorithmes 51 / 77


Algorithmes gloutons

Exemple : Problème du sac à dos

Problème du sac à dos (version simple)


Un ensemble d’articles U = {u 1 , u 2 , . . . , u N }
Chaque article a un poids p i et une valeur v i (p i , v i ∈ N)
Le poids maximum que peut contenir le sac à dos P
Comment choisir des fractions des articles à mettre dans le sac à dos
pour maximiser la valeur globale transportée ?

Hicham Bensaid (Département RIM) Conception des algorithmes 52 / 77


Algorithmes gloutons

Problème du sac à dos : construire une solution gloutonne

Chaque article i choisi contribue avec x i p i dans le poids total


et avec x i v i dans la valeur globale transportée
Il s’agit de résoudre :
maximiser ni=1 x i v i
P

sous la contrainte P ≥ ni=1 x i p i


P

avec v i > 0, p i > 0 et 0 ≤ x i ≤ 1


Solution gloutonne : les candidats sont les différents objets
La solution = {x 1 , . . . , x n } est faisable si elle respecte les contraintes
la fonction objectif = valeur totale transportée
Pn
Remarque : si i =1 p i ≤ P alors la solution est triviale . . . et si
Pn
x p
i =1 i i < P alors on peut toujours ajouter une fraction pour remplir
⇒ dans une solution optimale : ni=1 x i p i = P
P

Hicham Bensaid (Département RIM) Conception des algorithmes 53 / 77


Algorithmes gloutons

Algorithme glouton
Entrée : un ensemble C et un poids maximimum P du sac à dos
Résultat : une configuration x1 , . . . , xn optimale
1 function sacADosGlouton(C , P ) // C est un ensemble d’articles
2 S =; // Le sous-ensemble solution est construit dans S
3 for i = 1 to n do // initialisation
4 x[i ] = 0
5 poi d s = 0
6 while C 6= ; and poi d s < P do
7 c = sel ect i on(C )
8 C =C −c
9 if poi d s + [Link] d s ≤ P then
10 x[i ] = 1
11 poi d s = poi d s + [Link] d s
12 else
13 x[1] = (P − poi d s)/[Link] d s
14 poi d s = P

15 return x
Algorithme 11 : sacADosGlouton
Hicham Bensaid (Département RIM) Conception des algorithmes 54 / 77
Algorithmes gloutons

Algorithme glouton
La question est comment choisir le bon candidat ?
à chaque fois au moins trois possibilités :
Choisir l’article restant ayant la plus grande valeur
Choisir l’article restant le plus léger
Choisir l’article restant ayant le meilleur rapport v i /p i
Exemple : pour n = 5 et P = 100
p 10 20 30 40 50
v 20 30 66 40 60
v/p 2.0 1.5 2.2 1.0 1.2

sélection xi valeur
max v i 0 0 1 0.5 1 146
min p i 1 1 1 1 0 156
max v i /p i 1 1 1 0 0.8 164

Hicham Bensaid (Département RIM) Conception des algorithmes 55 / 77


Algorithmes gloutons

Solution optimale

Les deux premiers critères ne sont pas optimaux, le troisième l’est-il ?


La réponse est oui.
Pourquoi ? : le théorème suivant

Théorème
Si les articles sont choisis dans l’ordre décroissant des v i /p i alors
sacADosGlouton trouve une solution optimale.

Démonstration.
On suppose (s.p.g.) que v 1 /p 1 ≥ v 2 /p 2 ≥ . . . ≥ v n /p n . X = (x 1 , . . . , x n )
solution optimale.

Hicham Bensaid (Département RIM) Conception des algorithmes 56 / 77


Algorithmes gloutons

Solution optimale
Démonstration.
(suite)
Si tous les x i = 1 alors la solution est optimale
Sinon, soit j le plus petit indice tq x j < 1
∀i < j x i = 1 et ∀i > j x i = 0 et ni=1 x i p i = P
P

Soit Y = y 1 , . . . , y n une solution réalisable. donc ni=1 y i p i ≤ P et


¡ ¢ P
Pn
i =1 (x i − y i )p i ≥ 0
V (X ) − V (Y ) = ni=1 (x i − y i )p i . pv ii
P

On va montrer que (x i − y i )(v i /p i ) ≥ (x i − y i )(v j /p j )


Si i < j , x i = 1 et donc (x i − y i ) ≥ 0 et v i /p i ≥ v j /p j
Si i > j , x i = 0 et donc (x i − y i ) ≤ 0 et v i /p i ≤ v j /p j
si i = j , v i /p i = v j /p j et donc (x i − y i )(v i /p i ) = (x i − y i )(v j /p j )
V (X ) − V (Y ) ≥ (v j /p j ) ni=1 (x i − y i )p i ≥ 0
P

⇒ Aucune solution réalisable n’est meilleure que V (X )


Hicham Bensaid (Département RIM) Conception des algorithmes 57 / 77
Algorithmes gloutons

Limites de l’approche gloutonne


Le problème du sac à dos entier est une variation du problème
précédent
Pas de fractions : ou bien un article est retenu ou bien il ne l’est pas
Exemple : n = 3 et P = 50
p 10 20 30
v 60 100 120
v/p 6 5 4
Une stratégie gloutonne commencerait par choisir l’article 1
ou bien 1 + 2 : valeur = 160
ou bien 1 + 3 : valeur = 180
Solutions non optimales ! !
La solution optimale dans ce cas est 2 + 3 : valeur = 220
La programmation dynamique permet de résoudre le problème
Mais c’est un problème très coûteux (on ne lui connait aucune solution
polynomiale)
Hicham Bensaid (Département RIM) Conception des algorithmes 58 / 77
Diviser pour régner

Plan

1 Motivations

2 Programmation dynamique
Dégroupage optimal
Multiplication optimale d’une chaine de matrices

3 Algorithmes gloutons

4 Diviser pour régner


Tri par fusion
Tri rapide (quicksort)

Hicham Bensaid (Département RIM) Conception des algorithmes 59 / 77


Diviser pour régner Tri par fusion

Tri par fusion : la fusion


Complexité linéaire : Θ(n)
Entrée : un tableau T , trois indices p, q, r tels que T [p..q] et T [q + 1, r ] sont triés
Résultat : T [p..r ] est trié
1 procedure fusion(T, p, q, r )
2 n1 = q − p + 1
3 n2 = r − q
4 Soient G[1..n 1 + 1] et D[1..n 2 + 1] deux nouveaux tableaux
5 G[1..n 1 ] = T [p..q]
6 D[1..n 2 ] = T [q + 1..r ]
7 G[n 1 + 1] = ∞
8 D[n 2 + 1] = ∞
9 i = j =1
10 for k = p to r do
11 if G[i ] ≤ D[ j ] then
12 T [k] = G[i + +]
13 else
14 T [k] = D[ j + +]
Hicham Bensaid (Département RIM) Conception des algorithmes 60 / 77
Diviser pour régner Tri par fusion

Tri par fusion

Complexité en Θ(n lg n) : si n ∈ 2N alors t (n) = 2t (n/2) + Θ(n)


Entrée : un tableau T , deux indices p, r
Résultat : T est trié
1 procedure triFusion(T, p, r )
2 if p < r ¥then ¦
3 q = (p + r )/2
4 triFusion(T, p, q )
5 triFusion(T, q + 1, r )
6 fusion(T, p, q, r )
Algorithme 13 : triFusion

Hicham Bensaid (Département RIM) Conception des algorithmes 61 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort

algorithme de tri de complexité dans le pire cas en Θ(n 2 )


mais en pratique c’est le meilleur :
complexité moyenne en Θ(n lg(n)) et constantes cachées faibles
effectue le tri sur place
fondé sur la stratégie diviser pour régner
diviser : partitionner en réarrangeant T [p..r ] en 2 sous tableaux
T1 = T [p..q − 1] et T2 = T [q + 1..r ] tq T [i ] ≤ T [q] ≤ T [ j ]
pour i ∈ [p..q − 1] et j ∈ [q + 1..r ]. Le calcul de q est le
résultat de cette procédure
régner : trier T1 et T2 récursivement par quicksort
combiner : il n’y a rien à faire ...

Hicham Bensaid (Département RIM) Conception des algorithmes 62 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : l’algorithme

Entrée : un tableau T , deux indices p, r


Résultat : T [p..r ] trié
1 procedure quicksort(T, p, r )
2 if p < r then
3 q = partitionner(T, p, r )
4 quicksort(T, p, q − 1)
5 quicksort(T, q + 1, r )
Algorithme 14 : quicksort
Pour trier un tableau T il suffit d’exécuter quicksort(T, 1, T.t ai l l e )

Hicham Bensaid (Département RIM) Conception des algorithmes 63 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : partitionner

Entrée : un tableau T , deux indices p, r


Résultat : q la position du pivot
1 function partitionner(T, p, r )
2 x = T [r ]
3 i = p −1
4 for j = p to r − 1 do
5 if T [ j ] ≤ x then
6 i = i +1
7 échanger T [i ] et T [ j ]

8 q = i +1
9 échanger T [q] et T [r ]
10 return q
Algorithme 15 : partitionner

Hicham Bensaid (Département RIM) Conception des algorithmes 64 / 77


Diviser pour régner Tri rapide (quicksort)

Exemple

T [r ] est le pivot x
Les éléments en gris clair =
première partition (tous ≤ x )
Les éléments en gris foncé =
deuxième partition (tous > x )
Les autres ne sont pas encore
traités
(Le dernier élément est le pivot)
A la dernière étape on échange
T [r ] et T [i + 1]

Hicham Bensaid (Département RIM) Conception des algorithmes 65 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : comment ça marche ?

Si T [ j ] > x , on incrémente j
Si T [ j ] ≤ x on incrémente i , puis on échange T [i ] et T [ j ] enfin on
incrémente j
Hicham Bensaid (Département RIM) Conception des algorithmes 66 / 77
Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le pire cas


On va démontrer que dans le pire cas T (n) = Θ(n 2 )
On démontre que T (n) = O(n 2 ) et T (n) = Ω(n 2 )
Dans le pire cas on a l’équation de récurrence
¡ ¢
T (n) = max T (q) + T (n − q − 1) + Θ(n)
0≤q≤n−1

S. q. T (k) ≤ ck 2 ∀k ≤ n − 1 et remplaçons dans la récurrence


T (n) ≤ max (c q 2 + c(n − q − 1)2 ) + Θ(n) =
0≤q≤n−1
c. max (q 2 + (n − q − 1)2 ) + Θ(n)
0≤q≤n−1
Le maximum est atteint pour q = 0 ou q = n − 1
donc max (q 2 + (n − q − 1)2 ) ≤ (n − 1)2
0≤q≤n−1
et T (n) ≤ cn − c(2n − 1) + Θ(n) ≤ cn 2 en prenant c suffisamment
2

grande pour que c(2n − 1) domine le terme en Θ(n)


Attention aux conditions aux limites ! ! !
Donc T (n) = O(n 2 )
Hicham Bensaid (Département RIM) Conception des algorithmes 67 / 77
Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le pire cas

On démontre que T (n) = Ω(n 2 )


Dans le pire cas on a l’équation de récurrence
¡ ¢
T (n) = max T (q) + T (n − q − 1) + Θ(n)
0≤q≤n−1

S. q. T (k) ≥ d k 2 ∀k ≤ n − 1 et remplaçons dans la récurrence


T (n) ≥ max (d .q 2 + d .(n − q − 1)2 ) + Θ(n) ≥ d .(n − 1)2 + Θ(n)
0≤q≤n−1

et T (n) ≥ d .n 2 − d (2n − 1) + Θ(n) ≥ d n 2 en prenant d suffisamment


petite pour que d (2n − 1) soit dominé par le terme en Θ(n)
Attention aux conditions aux limites ! ! !
Donc T (n) = Ω(n 2 )
Conclusion : T (n) = Θ(n 2 ) dans le pire cas

Hicham Bensaid (Département RIM) Conception des algorithmes 68 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le meilleur cas

On va démontrer que dans le meilleur cas T (n) = Θ(n lg n)


¡ ¢
Dans le meilleur cas : T (n) = min T (q) + T (n − q − 1) + Θ(n)
0≤q≤n−1
S. q. T (k) ≤ c.k lg k ∀k ≤ n − 1 et remplaçons dans la récurrence
¡ ¢
T (n) ≤ min c.q lg q + c.(n − q − 1) lg(n − q − 1) + Θ(n)
0≤q≤n−1
T (n) ≤ c.q 0 lg q 0 + c.(n − q 0 − 1) lg(n − q 0 − 1) + Θ(n) avec q 0 = (n − 1)/2
T (n) ≤ c. ((n − 1)/2) lg ((n − 1)/2) + c. ((n − 1)/2) lg ((n − 1)/2) + Θ(n)
donc T (n) ≤ c.(n − 1) lg(n − 1) − c.(lg 2.)(n − 1) + Θ(n)
et T (n) ≤ c.n. lg(n) (car n lg n ր) en choisissant c telle que
c.(lg 2.)(n − 1) domine la fonction en Θ(n)
Attention aux conditions aux limites (il faut les vérifier) . . .
Donc T (n) = O(n lg n) dans le meilleur cas

Hicham Bensaid (Département RIM) Conception des algorithmes 69 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le meilleur cas

On va démontrer que dans le meilleur cas T (n) = Ω(n lg n)


¡ ¢
T (n) = min T (q) + T (n − q − 1) + Θ(n)
0≤q≤n−1
S. q. T (k) ≥ c.k lg k ∀k ≤ n − 1 et remplaçons dans la récurrence
¡ ¢
T (n) ≥ min c.q lg q + c.(n − q − 1) lg(n − q − 1) + Θ(n)
0≤q≤n−1
¢′
f ′ (q) = c.q lg q + c.(n − q − 1) lg(n − q − 1) = lg q/(n − q − 1)
¡ ¡ ¢

lim f ′ (q) = −∞ et lim f ′ (q) = +∞ et


q→0+ q→n−1−

f ′′ (q) = (n − 1)(n − 1 − q)/(n − q − 1)2 ≥ 0 donc f ′ :−∞ ր 0 ր+∞ et


traverse 0 en q0 tq f ′ (q0 ) = 0

Hicham Bensaid (Département RIM) Conception des algorithmes 70 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le meilleur cas

f est donc : ց q 0 ր (minimum atteint en q 0 )


q 0 = n − q 0 − 1 ⇒ q 0 = (n − 1)/2 : l’optimum est atteint quand on divise
le tableau en deux
T (n) ≥ c. ((n − 1)/2) lg ((n − 1)/2) + c. ((n − 1)/2) lg ((n − 1)/2) + Θ(n)
donc T (n) ≥ c.(n − 1) lg(n − 1) − c.(lg 2.)(n − 1) + Θ(n)
¡ ¢
et T (n) ≥ c.n lg n + c.(n − 1) lg(n − 1) − cn lg n − c.(lg 2.)(n − 1) + Θ(n)

Hicham Bensaid (Département RIM) Conception des algorithmes 71 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité dans le meilleur cas

or c.(n − 1) lg(n − 1) − cn lg n = −n lg (1 + 1/(n − 1)) − lg(n − 1)


et lg (1 + 1/(n − 1)) ∼ 1/(n − 1) (D. L. de log au voisinage de 1)
donc c.(n − 1) lg(n − 1) − cn lg n ∼ −1 − lg(n − 1) ≥ −α lg(n)
donc
c.(n − 1) lg(n − 1) − cn lg n − c.(lg 2.)(n − 1) + Θ(n) ≥ −α lg(n) − βc n + Θ(n)
on choisissant c suffisamment petite pour que la fonction en Θ(n)
domine α lg(n) + βc n
On a T (n) ≥ c.n. lg(n)
Attention aux conditions aux limites (il faut les vérifier) . . .
Donc T (n) = Ω(n lg n) dans le meilleur cas
Donc T (n) = Θ(n lg n)

Hicham Bensaid (Département RIM) Conception des algorithmes 72 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité en moyenne

On suppose que les éléments sont équitablement répartis


Probabilité pour choisir un élément comme pivot parmi n éléments =
1/n

Temps d’exécution de Quicksort dominé par les appels à par t i t i on


Chaque appel à par t i t i on choisit un pivot
un pivot choisit n’est plus jamais choisi après
⇒ au plus n appels à par t i t i on

Hicham Bensaid (Département RIM) Conception des algorithmes 73 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : complexité en moyenne

Complexité de par t i t i on Entrée : un tableau T , deux


O(1) : toutes les opérations indices p, r
sauf la boucle for (lignes 4 à Résultat : q la position du pivot
7) 1 function partitionner(T, p, r )
une quantité proportionnelle 2 x = T [r ]
au nombre d’itération de la 3 i = p −1
boucle for (lignes 4 à 7) 4 for j = 1 to r − 1 do
Chaque itération effectue une 5 if T [ j ] ≤ x then
comparaison entre le pivot et 6 i = i +1
un autre élément du tableau 7 échanger T [i ] et T [ j ]
(ligne 5)
Il faut donc compter le 8 q = i +1
nombre total de 9échanger T [q] et T [r ]
10 return q
comparaisons
Hicham Bensaid (Département RIM)
Algorithme 16 : partitionner 74 / 77
Conception des algorithmes
Diviser pour régner Tri rapide (quicksort)

Quicksort : relation entre la complexité et le nombre de


comparaison

Lemme
Soit X le nombre de comparaisons exécutées dans la ligne 5 de par t i t i on
durant toute la durée d’une exécution de qui cksor t sur un tableau de
taille n
Le temps d’exécution de qui cksor t est O(n + X )

Démonstration.
Preuve immédiate

Hicham Bensaid (Département RIM) Conception des algorithmes 75 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : évaluation de X

On va compter le X global (et non pas combien de comparaisons à


chaque itération)
Z = {z 1 , . . . z n } où z i est le i ème plus petit élément
Zi j = {z i , z i +1 , . . . , z j }
Quand est ce qu’on compare z i et z j ?
chaque paire est comparée au plus une fois
on ne compare qu’avec le pivot qui n’est utilisé qu’une fois
X i j ∈ {0, 1} variable aléatoire de l’évènement comparaison de z i et z j
X = in−1
P Pn
=1 j =i +1 X i j

Hicham Bensaid (Département RIM) Conception des algorithmes 76 / 77


Diviser pour régner Tri rapide (quicksort)

Quicksort : évaluation de X

hP i
n−1 Pn
E [X ] = E i =1 j =i +1 X i j

E [X ] = in−1
P Pn £ ¤
=1 j =i +1 E X i j
E [X ] = in−1
Pn ¡ ¢
j =i +1 P r z i est comparé à z j
P
=1
z i est comparé à z j ssi z i ou z j est le pivot de Zi j
P r z i soit choisit comme pivot = j −i1+1 (les éléments sont
¡ ¢

équiprobables)
Pn−1 Pn 1
donc E [X ] = 2. i =1 j =i +1 j −i +1 soit par changement de variable
(k = j − i )
Pn−1 Pn 1
E [X ] = 2. i =1 k=1 k
E [X ] = O(n lg n)

Hicham Bensaid (Département RIM) Conception des algorithmes 77 / 77

Vous aimerez peut-être aussi