Algorithmique avancée
Embed Size (px)
Transcript of Algorithmique avancée
-
Algorithmique avanceIUP 2
Frdric Vivien
24 avril 2002
-
2
-
Table des matires
1 Introduction 91.1 Quest-ce que lalgorithmique ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.2 Motivation : calcul de xn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.1 Problme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.2.2 Algorithme trivial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.2.3 Mthode binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.2.4 Algorithme des facteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.2.5 Algorithme de larbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.2.6 Et aprs ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2 Complexit et optimalit ; premier algorithme de tri 132.1 Dfinition de la complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.1.1 Notations de Landau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.1.2 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.1.3 Modle de machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2 Illustration : cas du tri par insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.1 Problmatique du tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.2 Principe du tri par insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.3 Algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.4 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.5 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3 La rcursivit et le paradigme diviser pour rgner 173.1 Rcursivit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.1.1 Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.1.2 Rcursivit simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.1.3 Rcursivit multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.1.4 Rcursivit mutuelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.1.5 Rcursivit imbrique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.1.6 Principe et dangers de la rcursivit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.1.7 Non dcidabilit de la terminaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.1.8 Importance de lordre des appels rcursifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.1.9 Exemple dalgorithme rcursif : les tours de Hano . . . . . . . . . . . . . . . . . . . . . . . 20
3.2 Drcursivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.2.1 Rcursivit terminale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.2.2 Rcursivit non terminale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.2.3 Remarques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.3 Diviser pour rgner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.3.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.3.2 Premier exemple : multiplication nave de matrices . . . . . . . . . . . . . . . . . . . . . . . 243.3.3 Analyse des algorithmes diviser pour rgner . . . . . . . . . . . . . . . . . . . . . . . . . 24
3
-
4 TABLE DES MATIRES
3.3.4 Rsolution des rcurrences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253.3.5 Deuxime exemple : algorithme de Strassen pour la multiplication de matrices . . . . . . . . 25
4 Algorithmes de tri 294.1 Tri par fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294.1.2 Algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294.1.3 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.2 Tri par tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.2.1 Dfinition dun tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.2.2 Conservation de la structure de tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.2.3 Construction dun tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.2.4 Algorithme du tri par tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.3 Tri rapide (Quicksort) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.3.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.3.2 Algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364.3.3 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5 Structures de donnes lmentaires 395.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395.2 Piles et files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.2.1 Piles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395.2.2 Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.3 Listes chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425.3.1 Dfinitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425.3.2 Algorithmes de manipulation des listes chanes . . . . . . . . . . . . . . . . . . . . . . . . 435.3.3 Comparaison entre tableaux et listes chanes . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6 Programmation dynamique 476.1 Multiplication dune suite de matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476.2 lments de programmation dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.2.1 Sous-structure optimale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516.2.2 Sous-problmes superposs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516.2.3 Recensement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
7 Algorithmes gloutons 537.1 Location dune voiture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537.2 lments de la stratgie gloutonne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.2.1 Proprit du choix glouton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547.2.2 Sous-structure optimale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.3 Fondements thoriques des mthodes gloutonnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557.3.1 Matrodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557.3.2 Algorithmes gloutons sur un matrode pondr . . . . . . . . . . . . . . . . . . . . . . . . . 55
8 Graphes et arbres 578.1 Graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.2 Arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588.3 Parcours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8.3.1 Parcours des arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608.3.2 Parcours des graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
-
TABLE DES MATIRES 5
9 Arbres de recherche et arbres de recherche quilibrs 639.1 Arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.1.1 Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639.1.2 Recherches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639.1.3 Insertion dun lment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649.1.4 Suppression dun lment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649.1.5 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
9.2 Arbres rouge et noir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669.2.1 Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669.2.2 Rotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.2.3 Insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.2.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.2.5 Complexit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10 Plus courts chemins 7510.1 Plus courts chemins origine unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
10.1.1 Algorithme de Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7510.1.2 Algorithme de Bellman-Ford . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
10.2 Plus courts chemins pour tout couple de sommets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7810.2.1 Programmation dynamique nave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7910.2.2 Algorithme de Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
11 NP-compltude 8311.1 La classe P . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
11.1.1 Problmes abstraits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8311.1.2 Codage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
11.2 La classe NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8411.2.1 Algorithme de validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8411.2.2 La classe de complexit NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
11.3 NP-compltude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8511.3.1 Rductibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8511.3.2 Dfinition de la NP-compltude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8611.3.3 Exemples de problmes NP-complets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8611.3.4 Preuves de NP-compltude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
12 Heuristiques 8912.1 Le problme de la couverture de sommet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
12.1.1 Heuristique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9012.1.2 Exemple dutilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9012.1.3 Garantie de performances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
12.2 Le problme du voyageur de commerce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9112.2.1 Exemple dutilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9112.2.2 Garantie de performances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
-
6 TABLE DES MATIRES
-
Table des figures
1.1 Arbre de puissances. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.2 Schma de calcul pour n = 23. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.1 Exemple dutilisation de lalgorithme TRI-INSERTION. . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1 Mthode de rsolution du jeu des tours de Hano. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.2 Exemple dexcution de lalgorithme drcursiv. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.1 Algorithme FUSIONNER. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304.2 Algorithme TRI-FUSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304.3 Exemple de tas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.4 Algorithme ENTASSER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.5 Exemple dutilisation de lalgorithme ENTASSER. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.6 Algorithme CONSTRUIRE-TAS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.7 Exemple dutilisation de lalgorithme CONSTRUIRE-TAS. . . . . . . . . . . . . . . . . . . . . . . . 344.8 Exemple dutilisation de lalgorithme TRIER-TAS. . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.1 Exemple de manipulation de pile. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.2 Implmentation dune pile par un tableau. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.3 Algorithmes de manipulation des piles implmentes par des tableaux. . . . . . . . . . . . . . . . . . 415.4 Exemple de manipulation de file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.5 Implmentation dune file par un tableau. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.6 Algorithmes de manipulation des files implmentes par des tableaux. . . . . . . . . . . . . . . . . . 425.7 Exemple de manipulation de liste chane. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425.8 Exemple de manipulation de liste doublement chane. . . . . . . . . . . . . . . . . . . . . . . . . . 435.9 Efficacits respectives des listes chanes et des tableaux. . . . . . . . . . . . . . . . . . . . . . . . . 45
6.1 Illutration de lalgorithme ORDONNER-CHANEDEMATRICES. . . . . . . . . . . . . . . . . . . . . 50
8.1 Exemple de graphe orient. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.2 Exemple de graphe non orient. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.3 Exemple de graphe contenant un cycle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588.4 Exemple de fort. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588.5 Exemple darbre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588.6 Exemple darbres qui ne diffrent que sils sont enracins. . . . . . . . . . . . . . . . . . . . . . . . 598.7 Exemple darbres (enracins) qui ne diffrent que sils sont ordonns. . . . . . . . . . . . . . . . . . 598.8 Exemple darbres ordonns qui ne diffrent que quand ils sont vus comme des arbres binaires. . . . . 608.9 Algorithme de parcours en profondeur dun arbre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608.10 Parcours prfixe, infixe et postfixe dun arbre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608.11 Algorithme de parcours en largeur dun arbre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618.12 Algorithme de parcours en profondeur dun graphe. . . . . . . . . . . . . . . . . . . . . . . . . . . . 618.13 Algorithme de parcours en largeur dun graphe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7
-
8 TABLE DES FIGURES
9.1 Deux arbres binaires de recherche contenant les mmes valeurs. . . . . . . . . . . . . . . . . . . . . 639.2 Localisation du successeur. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649.3 Algorithme dinsertion dans un arbre binaire de recherche. . . . . . . . . . . . . . . . . . . . . . . . 659.4 Cas de figure lors de la suppression dun nud dun arbre binaire de recherche. . . . . . . . . . . . . 659.5 Suppression dun lment dans un arbre binaire de recherche. . . . . . . . . . . . . . . . . . . . . . . 669.6 Exemple darbre rouge et noir. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.7 Rotations sur un arbre binaire de recherche. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.8 Algorithme de rotation gauche pour un arbre binaire. . . . . . . . . . . . . . . . . . . . . . . . . . . 689.9 Premire srie de configurations pathologiques pour linsertion dans un arbre rouge et noir. . . . . . . 689.10 Deuxime srie de configurations pathologiques pour linsertion dans un arbre rouge et noir. . . . . . 699.11 Algorithme dinsertion dans un arbre rouge et noir. . . . . . . . . . . . . . . . . . . . . . . . . . . . 709.12 Exemple dinsertion dans un arbre rouge et noir. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719.13 Configurations pathologiques pour la suppression dans un arbre rouge et noir. . . . . . . . . . . . . . 729.14 Suppression dun lment dans un arbre rouge et noir. . . . . . . . . . . . . . . . . . . . . . . . . . . 739.15 Correction dun arbre rouge et noir aprs suppression dun lment. . . . . . . . . . . . . . . . . . . 74
10.1 Algorithme de Dijkstra pour le calcul des plus courts chemins. . . . . . . . . . . . . . . . . . . . . . 7610.2 Exemple dexcution de lalgorithme de Dijkstra. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7710.3 Algorithme de Bellman-Ford pour le calcul des plus courts chemins. . . . . . . . . . . . . . . . . . . 7710.4 Exemple dexcution de lalgorithme de Bellman-Ford. . . . . . . . . . . . . . . . . . . . . . . . . . 7810.5 Algorithme naf par programmation dynamique pour le calcul des plus courts chemins. . . . . . . . . 8010.6 Un graphe orient et la squence des matrices calcules par PLUS-COURTS-CHEMINS. . . . . . . . . 8010.7 Algorithme de Floyd-Warshall pour le calcul des plus courts chemins. . . . . . . . . . . . . . . . . . 8110.8 Exemple dexcution de lalgorithme de Floyd-Warshall. . . . . . . . . . . . . . . . . . . . . . . . . 82
12.1 Exemple dutilisation de lalgorithme COUVERTURE-SOMMET-APPROCHE. . . . . . . . . . . . . . 9012.2 Exemple dutilisation de lalgorithme TOURNE-APPROCHE. . . . . . . . . . . . . . . . . . . . . . 92
Avertissement
Ce cours ne traite pas : la recherche de motifs dans une chane de caractres (problme suppos tre abondamment trait dans le cours
de Programmation Oriente Objet) ; lalgorithmique gomtrique (suppose tre traite dans les cours lis au traitement dimage).
-
Chapitre 1
Introduction
1.1 Quest-ce que lalgorithmique ?
Dfinition 1 (Algorithme). Un algorithme est suite finie doprations lmentaires constituant un schma de calculou de rsolution dun problme.
Historique : Le mot algorithme provient de la forme latine (Algorismus) du nom du mathmaticien arabe AL-KHAREZMI ou AL-KHWARIZMI auteur entre autres mais ce n est pas le plus important dun manuel de vulga-risation sur le calcul dcimal positionnel indien (v. 830) expliquant son utilisation et, surtout, la manipulation desdiffrents algorithmes permettant de raliser les oprations arithmtiques classiques (addition, soustraction, multipli-cation, division, extraction de racines carres, rgle de trois, etc.).
Double problmatique de lalgorithmique
1. Trouver une mthode de rsolution (exacte ou approche) du problme. Soient trois nombres rels a, b et c, quelles sont les solutions de lquation ax2 + bx + c ? (Rsultat bien
connu.) Soient cinq nombres rels a, b, c, d et e, quelles sont les solutions de lquation ax5 +bx4 +cx3 +dx2 +ex+ f ?
(Pas de mthode gnrale, cf. la thorie de GALOIS.)
2. Trouver une mthode efficace.
Savoir rsoudre un problme est une chose, le rsoudre efficacement en est une autre, comme nous allons le voir la section 1.2.
Diffrences entre algorithmes et programmes
Un programme est la ralisation (limplmentation) dun algorithme au moyen dun langage donn (sur unearchitecture donne). Il sagit de la mise en uvre du principe. Par exemple, lors de la programmation on soccuperaparfois explicitement de la gestion de la mmoire (allocation dynamique en C) qui est un problme dimplmentationignor au niveau algorithmique.
1.2 Motivation : calcul de xn
1.2.1 Problme
Donnes : un entier naturel n et un rel x. On veut calculer xn.
Moyens : Nous partons de y1 = x. Nous allons construire une suite de valeurs y1, ..., ym telle que la valeur yk soitobtenue par multiplication de deux puissances de x prcdemment calcules : yk = yu yv, avec 1 u,v < k,k [2,m].
9
-
10 CHAPITRE 1. INTRODUCTION
But : ym = xn. Le cot de lalgorithme sera alors de m1, le nombre de multiplications faites pour obtenir le rsultatrecherch.
1.2.2 Algorithme trivial
yi = yi1 y1, i [2,n]. Rsultat : yn = xn. Cot : m1 = n1 multiplications.
Algorithme
y[1] = xPour i 2 n faire
y[i] = y[i1] y[1]renvoyer y[n]
1.2.3 Mthode binaire
Algorithme
1. crire n sous forme binaire
2. Remplacer chaque : 1 par la paire de lettres SX ; 0 par la lettre S .
3. liminer la paire SX la plus gauche.
4. Rsultat : un mode de calcul de xn o S signifie lever au carr (squaring) ; X signifie multiplier par x .Le tout en partant de x.
Illustration avec n = 23
1. n = 101111 0 1 1 1
2. SX S SX SX SX
3. S SX SX SX
4. Nous partons de x et nous obtenons successivement :x2, x4, x5, x10, x11, x22, x23.Nous sommes donc capables de calculer x23 en 7 multiplications au lieu de 22 !
Explication de la mthode
criture binaire de n : n = i=pi=0 ai2i.
Plaons nous au cours du calcul de puissances de x. Soit j le dernier bit de la reprsentation binaire de n qui aitt dcod et soit y j le dernier rsultat obtenu. Initialement, j = p et yp = x = xap .
Deux cas sont possibles pour a j1 :
1. a j1 = 1. a j1 est remplac par SX, nous levons y j au carr puis multiplions le rsultat par x. Le nouveaursultat est y j1 = y2j x.
2. a j1 = 0. a j1 est remplac par S et nous levons simplement y j au carr. Le nouveau rsultat est y j1 = y2j .
Dans tous les cas nous avons : y j1 = y2j (xa j1). Do, yp1 = y2p (xap1) = (xap)
2 (xap1) = (x2ap) (xap1) = (x2ap+ap1). Par rcurrence, nous pouvonsmontrer que y1 = x
i=pi=0 ai2
i= xn...
-
1.2. MOTIVATION : CALCUL DE XN 11
Complexit (cot)
Note : les nombres dont la reprsentation binaire a exactement p chiffres forment exactement lintervalle [2p1,2p1].Nombres de chiffres dans lcriture binaire de n : 1+[log2 n]. Notons (n) le nombre de 1 dans lcriture binaire
de n. Nombre doprations effectues : (1 +[log2 n])1 lvations au carr (ne pas oublier ltape 3) ; (n)1 multiplications par x (ne pas oublier ltape 3).
Soit en tout T (n) = [log2 n]+(n)1 multiplications. Trivialement, 1 (n) [log2 n] et [log2 n] T (n) 2[log2 n].Pour n = 1000, lalgorithme trivial effectue 999 multiplications, et la mthode binaire moins de 20.
Historique
Cette mthode a t prsente avant 200 avant J.C. en Inde, mais il semblerait quil ait fallu attendre un millnaireavant que cette mthode ne soit connue en dehors de lInde [3, p. 441].
Peut-on faire mieux ?
Prenons le cas n = 15.
1. n = 11111 1 1 1
2. SX SX SX SX
3. SX SX SX
4. Nous partons de x et nous obtenons successivement : x2, x3, x6, x7, x14, x15. Nous sommes donc capables decalculer x15 en 6 multiplications.
Autre schma de calcul : x2, x3, x6, x12, x15 = x12 x3. Nous obtenons ainsi x15 en 5 multiplications et la mthodebinaire nest donc pas optimale (cest--dire que lon peut faire mieux).
1.2.4 Algorithme des facteurs
Algorithme
xn =
x si n = 1;
xn1 x si n premier;(xp)n
si n = pn avec p plus petit diviseur premier de n.
Illustration avec n = 15
1. 15 = 35, 3 tant le plus petit diviseur (facteur) premier de 15. Donc x15 = (x3)5.Nous rappliquons lalgorithme pour calculer x3 et y5, o y = x3.
2. Calcul de x3 :
(a) 3 est premier. Donc x3 = x2 x. Nous rappliquons lalgorithme pour calculer x2.(b) 2 est premier. Donc x2 = x x.(c) Finalement, x3 est calcul comme suit : x3 = x x x, soit en deux multiplications.
3. Calcul de y5 :
(a) 5 est premier. Donc y5 = y4 y. Nous rappliquons lalgorithme pour calculer y4.(b) 4 = 22, o 2 est le plus petit facteur premier de 4. Donc y4 = (y2)2.(c) Finalement y5 est calcul comme suit : t = y y, u = t t, y5 = u y, soit en 3 multiplications.
4. Finalement, x15 est calcul en 5 multiplications.
-
12 CHAPITRE 1. INTRODUCTION
Peut-on faire mieux ?
Oui...
1.2.5 Algorithme de larbre
Le k + 1e niveau de larbre est dfini comme suit : on suppose que lon a dj les k premiers niveaux ; on construit le k +1e de la gauche vers la droite en ajoutant sous le nud n les nuds de valeur n+1, n+a1, ...,
n + ak1 o 1, a1, ..., ak1 est le chemin de la racine au nud n ; on supprime tous les nuds qui dupliquent une valeur dj obtenue.
Cf. la figure 1.1.
FIG. 1.1 Arbre de puissances (minimisant le nombrede multiplications pour n 76 [3]).
FIG. 1.2 Schma de calcul pour n = 23.
Illustration avec n = 23
Sur la figure 1.2 nous pouvons constater que cette mthode permet de calculer x23 en 6 multiplications, au lieu de7 pour la mthode binaire et celle des facteurs... Cette mthode nest optimale que pour n 76.
1.2.6 Et aprs ?
KNUTH [3] consacre prs de 26 pages ce problme...
Moralit : nous avons affaire un problme simple, que tout le monde sait rsoudre, mais quil est trs difficile dersoudre efficacement...
Dans ce cours nous verrons des problmes classiques, des mthodes classiques de rsolutions (qui ne rsoudronspas tout, loin sen faut), des structures de donnes classiques.
1.3 Conclusion
Pour conclure, citons [2] : Un bon algorithme est comme un couteau tranchant il fait exactement ce que lonattend de lui, avec un minimum defforts. Lemploi dun mauvais algorithme pour rsoudre un problme revient essayer de couper un steak avec un tournevis : vous finirez sans doute par obtenir un rsultat digeste, mais vous ac-complirez beaucoup plus defforts que ncessaire, et le rsultat aura peu de chances dtre esthtiquement satisfaisant.
-
Chapitre 2
Complexit et optimalit ; premieralgorithme de tri
2.1 Dfinition de la complexit
2.1.1 Notations de Landau
Quand nous calculerons la complexit dun algorithme, nous ne calculerons gnralement pas sa complexitexacte, mais son ordre de grandeur. Pour ce faire, nous avons besoin de notations asymptotiques.
O : f = O(g) n0,c 0,n n0, f (n) cg(n)
: f = (g) g = O( f )
o : f = o(g) c 0,n0,n n0, f (n) cg(n)
: f = (g) f = O(g) et g = O( f )
Exemples
O : n = O(n), 2n = O(3n), n+2 = O(n) (pour sen convaincre, prendre n0 = 2 et c = 2),
n = O(n), log(n) = O(n),n = O(n2).
o :
n = o(n), log(n) = o(n), n = o(n2), log(n) = o(
n).
: n + log(n) = (n +
n).
2.1.2 Complexit
Dfinition 2 (Complexit). La complexit dun algorithme est la mesure du nombre doprations fondamentales quileffectue sur un jeu de donnes. La complexit est exprime comme une fonction de la taille du jeu de donnes.
Nous notons Dn lensemble des donnes de taille n et T (d) le cot de lalgorithme sur la donne d.
Complexit au meilleur : Tmin(n) = mindDn C(d). Cest le plus petit nombre doprations quaura excuter lalgo-rithme sur un jeu de donnes de taille fixe, ici n. Cest une borne infrieure de la complexit de lalgorithmesur un jeu de donnes de taille n.
Complexit au pire : Tmax(n) = maxdDn C(d). Cest le plus grand nombre doprations quaura excuter lalgo-rithme sur un jeu de donnes de taille fixe, ici n.
Avantage : il sagit dun maximum, et lalgorithme finira donc toujours avant davoir effectu Tmax(n) oprations.Inconvnient : cette complexit peut ne pas reflter le comportement usuel de lalgorithme, le pire cas pouvantne se produire que trs rarement, mais il nest pas rare que le cas moyen soit aussi mauvais que le pire cas.
13
-
14 CHAPITRE 2. COMPLEXIT ET OPTIMALIT ; PREMIER ALGORITHME DE TRI
Complexit en moyenne : Tmoy(n) =dDn C(d)|Dn| . Cest la moyenne des complexits de lalgorithme sur des jeux de
donnes de taille n (en toute rigueur, il faut bien videmment tenir compte de la probabilit dapparition dechacun des jeux de donnes).
Avantage : reflte le comportement gnral de lalgorithme si les cas extrmes sont rares ou si la complexitvarie peu en fonction des donnes.
Inconvnient : la complexit en pratique sur un jeu de donnes particulier peut tre nettement plus importanteque la complexit en moyenne, dans ce cas la complexit en moyenne ne donnera pas une bonne indication ducomportement de lalgorithme.
En pratique, nous ne nous intresserons qu la complexit au pire et la complexit en moyenne.
Dfinition 3 (Optimalit). Un algorithme est dit optimal si sa complexit est la complexit minimale parmi lesalgorithmes de sa classe.
Nous nous intresserons quasi exclusivement la complexit en temps des algorithmes. Il est parfois intressant desintresser dautres de leurs caractristiques, comme la complexit en espace (taille de lespace mmoire utilis), lalargeur de bande passante requise, etc.
2.1.3 Modle de machine
Pour que le rsultat de lanalyse dun algorithme soit pertinent, il faut avoir un modle de la machine sur laquellelalgorithme sera implment (sous forme de programme). On prendra comme rfrence un modle de machine accs alatoire (RAM) et processeur unique, o les instructions sont excutes lune aprs lautre, sans oprationssimultanes.
2.2 Illustration : cas du tri par insertion
2.2.1 Problmatique du tri
Entre : une squence de n nombres, a1, ..., an.
Sortie : une permutation, a1, ..., an, de la squence dentre, telle que a
1 a2 ... an.
2.2.2 Principe du tri par insertion
De manire rpte, on retire un nombre de la squence dentre et on linsre la bonne place dans la squencedes nombres dj tris (ce principe est le mme que celui utilis pour trier une poigne de cartes).
2.2.3 Algorithme
TRI-INSERTION
Pour j 2 n fairecl A[ j]i j1tant que i> 0 et A[i] > cl faire
A[i + 1] A[i]i i1
A[i + 1] cl
On retire un nombre de la squence dentreLes j1 premiers lments de A sont dj tris.Tant que lon nest pas arriv au dbut du tableau,et que llment courant est plus grand que celui insrer.
On dcale llment courant (on le met dans la place vide).On sintresse llment prcdent.
Finalement, on a trouv o insrer notre nombre.
2.2.4 Exemple
Les diffrentes tapes de lexcution de lalgorithme TRI-INSERTION sur le tableau [5;2;4;6;1;3] sont prsentesfigure 2.1.
-
2.2. ILLUSTRATION : CAS DU TRI PAR INSERTION 15
FIG. 2.1 Action de TRI-INSERTION sur le tableau [5;2;4;6;1;3] ; llment insrer est entour par un cercle.
2.2.5 Complexit
Nous passons en revue les diffrentes tapes de notre algorithme afin dvaluer son temps dexcution. Pour cefaire, nous attribuons un cot en temps chaque instruction, et nous comptons le nombre dexcutions de chacune desinstructions. Pour chaque valeur de j [2,n], nous notons t j le nombre dexcutions de la boucle tant que pour cettevaleur de j. Il est noter que la valeur de t j dpend des donnes...
TRI-INSERTION
Pour j 2 n fairecl A[ j]i j1tant que i> 0 et A[i] > cl faire
A[i + 1] A[i]i i1
A[i + 1] cl
Cot
c1c2c3c4c5c6c7
Nombre dexcutions
nn1n1nj=2 t jnj=2(t j1)nj=2(t j1)n1
Le temps dexcution total de lalgorithme est alors :
T (n) = c1n + c2(n1)+ c3(n1)+ c4n
j=2
t j + c5n
j=2
(t j1)+ c6n
j=2
(t j1)+ c7(n1)
Complexit au meilleur : le cas le plus favorable pour lalgorithme TRI-INSERTION est quand le tableau est djtri, comme le montre le cas j = 4 de la figure 2.1. Dans ce cas t j = 1 pour tout j.
T (n) = c1n + c2(n1)+ c3(n1)+ c4(n1)+ c7(n1)= (c1 + c2 + c3 + c4 + c7)n (c2 + c3 + c4 + c7).
T (n) peut ici tre crit sous la forme T (n) = an + b, a et b tant des constantes indpendantes des entres, etT (n) est donc une fonction linaire de n.Le plus souvent, comme cest le cas ici, le temps dexcution dun algorithme est fix pour une entre donne ;mais il existe des algorithmes alatoires intressants dont le comportement peut varier mme pour une entrefixe. Nous verrons un algorithme de ce style au chapitre 4 : une version alatoire du tri rapide
Complexit au pire : le cas le plus dfavorable pour lalgorithme TRI-INSERTION est quand le tableau est dj tridans lordre inverse, comme le montre le cas j = 5 de la figure 2.1. Dans ce cas t j = j pour tout j.
Rappel : nj=1 j =n(n+1)
2 . Donc nj=2 j =
n(n+1)2 1 et
nj=2( j1) =
n(n1)2 .
T (n) = c1n + c2(n1)+ c3(n1)+ c4(
n(n+1)21)
+ c5
(n(n1)
2
)+ c6
(n(n1)
2
)+ c7(n1)
=(c4
2+
c52
+c62
)n2 +
(c1 + c2 + c3 +
c42 c5
2 c6
2+ c7
)n (c2 + c3 + c4 + c7).
T (n) peut ici tre crit sous la forme T (n) = an2 + bn + c, a, b et c tant des constantes, et T (n) est donc unefonction quadratique de n.
-
16 CHAPITRE 2. COMPLEXIT ET OPTIMALIT ; PREMIER ALGORITHME DE TRI
Complexit en moyenne : supposons que lon applique lalgorithme de tri par insertion n nombres choisis au ha-sard. Quelle sera la valeur de t j ? Cest--dire, o devra-t-on insrer A[ j] dans le sous-tableau A[1.. j 1] ?En moyenne, pour moiti les lments de A[1.. j 1] sont infrieurs A[ j], et pour moiti suprieurs. Donct j = j/2. Si lon reporte cette valeur dans lquation dfinissant T (n), on obtient, comme dans le pire cas, unefonction quadratique en n.Caveat : ce raisonnement est partiellement faux ; un raisonnement prcis doit bien videmment tenir compte desvaleurs des lments dj tris. Pour un calcul prcis, voir KNUTH [4, p. 82]. CORI et LVY [1, p. 26] font unautre raisonnement et trouve un autre rsultat (de mme ordre de grandeur). Les deux sont justes : tout dpend delhypothse que lon prend sur les jeux de donnes. Ainsi [1] suppose que les permutations sont quiprobables,et [4] que les valeurs trier sont quiprobables...
Ordre de grandeur
Ce qui nous intresse vraiment, cest lordre de grandeur du temps dexcution. Seul le terme dominant de laformule exprimant la complexit nous importe, les termes dordres infrieurs ntant pas significatifs quand n devientgrand. On ignore galement le coefficient multiplicateur constant du terme dominant. On crira donc, propos de lacomplexit du tri par insertion :
meilleur cas : (n).pire cas : (n2).en moyenne : (n2).
En gnral, on considre quun algorithme est plus efficace quun autre si sa complexit dans le pire cas a un ordrede grandeur infrieur.
Classes de complexit
Les algorithmes usuels peuvent tre classs en un certain nombre de grandes classes de complexit : Les algorithmes sub-linaires dont la complexit est en gnral en O(logn). Les algorithmes linaires en complexit O(n) et ceux en complexit en O(n logn) sont considrs comme ra-
pides. Les algorithmes polynomiaux en O(nk) pour k > 3 sont considrs comme lents, sans parler des algorithmes
exponentiels (dont la complexit est suprieure tout polynme en n) que lon saccorde dire impraticablesds que la taille des donnes est suprieure quelques dizaines dunits.
-
Chapitre 3
La rcursivitet le paradigme diviser pour rgner
3.1 Rcursivit
De lart dcrire des programmes qui rsolvent des problmes que lon ne sait pas rsoudre soi-mme !
3.1.1 Dfinition
Dfinition 4 (Dfinition rcursive, algorithme rcursif). Une dfinition rcursive est une dfinition dans laquelleintervient ce que lon veut dfinir. Un algorithme est dit rcursif lorsquil est dfini en fonction de lui-mme.
Dans le cadre de ce cours, nous ne nous intresserons quaux programmes et algorithmes rcursifs. Mais la notionde dfinition rcursive est beaucoup plus gnrale :
en mathmatiques : dfinition de lexponentielle : x R, f (x) = f (x) et f (0) = 1.en programmation : dfinition en Ocaml dune liste infinie dont tous les lments valent 1 :
let rec z = 1::z ; ;
3.1.2 Rcursivit simple
Revenons la fonction puissance x 7 xn. Cette fonction peut tre dfinie rcursivement :
xn ={
1 si n = 0;x xn1 si n 1.
Lalgorithme correspondant scrit :
PUISSANCE (x, n)
Si n = 0 alors renvoyer 1sinon renvoyer xPUISSANCE(x, n1)
3.1.3 Rcursivit multiple
Une dfinition rcursive peut contenir plus dun appel rcursif. Nous voulons calculer ici les combinaisons Cpn ense servant de la relation de Pascal :
Cpn ={
1 si p = 0 ou p = n;Cpn1 +C
p1n1 sinon.
Lalgorithme correspondant scrit :
17
-
18 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
COMBINAISON (n, p)
Si p = 0 ou p = n alors renvoyer 1sinon renvoyer COMBINAISON (n1, p) + COMBINAISON (n1, p1)
Bref, rien de particulier...
3.1.4 Rcursivit mutuelle
Des dfinitions sont dites mutuellement rcursives si elles dpendent les unes des autres. a peut tre le cas pourla dfinition de la parit :
pair(n) ={
vrai si n = 0;impair(n1) sinon; et impair(n) =
{faux si n = 0;
pair(n1) sinon.
Les algorithmes correspondants scrivent :PAIR (n)
Si n = 0 alors renvoyer vraisinon renvoyer IMPAIR (n1)
IMPAIR (n)
Si n = 0 alors renvoyer fauxsinon renvoyer PAIR (n1)
3.1.5 Rcursivit imbrique
La fonction dAckermann est dfinie comme suit :
A(m,n) =
n + 1 si m = 0A(m1,1) si m> 0 et n = 0A(m1,A(m,n1)) sinondo lalgorithme :
ACKERMANN(m, n)
si m = 0alors n + 1sinon si n = 0 alors ACKERMANN(m1, 1)
sinon ACKERMANN(m1, ACKERMANN(m, n1))
En rsum : on peut utiliser la rcursivit comme lon veut, peu prs nimporte comment...
3.1.6 Principe et dangers de la rcursivit
Principe et intrt : ce sont les mmes que ceux de la dmonstration par rcurrence en mathmatiques. On doit avoir : un certain nombre de cas dont la rsolution est connue, ces cas simples formeront les cas darrt de la
rcursion ; un moyen de se ramener dun cas compliqu un cas plus simple .La rcursivit permet dcrire des algorithmes concis et lgants.
Difficults : la dfinition peut tre dnue de sens :
Algorithme A(n)renvoyer A(n)
il faut tre srs que lon retombera toujours sur un cas connu, cest--dire sur un cas darrt ; il nous fautnous assurer que la fonction est compltement dfinie, cest--dire, quelle est dfinie sur tout son domainedapplications.
Moyen : existence dun ordre strict tel que la suite des valeurs successives des arguments invoqus par la dfinitionsoit strictement monotone et finit toujours par atteindre une valeur pour laquelle la solution est explicitementdfinie.Lalgorithme ci-dessous teste si a est un diviseur de b.
-
3.1. RCURSIVIT 19
DIVISEUR (a,b)Si a 0 alors Erreur
sinon si a b alors a = b (test dgalit)sinon DIVISEUR(a,ba)
La suite des valeurs b, ba, b2a, etc. est strictement dcroissante, car a est strictement positif, et on finittoujours pas aboutir un couple darguments (a,b) tel que ba est ngatif, cas dfini explicitement.Cette mthode ne permet pas de traiter tous les cas :
SYRACUSE(n)Si n = 0 ou n = 1 alors 1
sinon si n mod 2 = 0 alors SYRACUSE (n/2)sinon SYRACUSE (3n + 1)
Problme ouvert : lalgorithme est bien dfini et vaut 1 sur N.Question : Ny a-t-il vraiment aucun moyen de dterminer automatiquement si un algorithme rcursif quelconque va
terminer ? Rponse la section suivante...
3.1.7 Non dcidabilit de la terminaison
Question : peut-on crire un programme qui vrifie automatiquement si un programme donn P termine quand ilest excut sur un jeu de donnes D ?
Entre Un programme P et un jeu de donnes D.
Sortie vrai si le programme P termine sur le jeu de donnes D, et faux sinon.
Dmonstration de la non dcidabilit
Supposons quil existe un tel programme, nomm termine, de vrification de la terminaison. partir de ceprogramme on conoit le programme Q suivant :
programme Q
rsultat = termine(Q, /0)tant que rsultat = vrai faire attendre une seconde fin tant querenvoyer rsultat
Supposons que le programme Q qui ne prend pas darguments termine. Donc termine(Q, /0) renvoie vrai, ladeuxime instruction de Q boucle indfiniment et Q ne termine pas. Il y a donc contradiction et le programme Q netermine pas. Donc, termine(Q, /0) renvoie faux, la deuxime instruction de Q ne boucle pas, et le programme Q terminenormalement. Il y a une nouvelle fois contradiction : par consquent, il nexiste pas de programme tel que termine,cest--dire qui vrifie quun programme termine ou non sur un jeu de donnes...
Le problme de la terminaison est indcidable !
Petit historique : cf. [1, p. 48].
3.1.8 Importance de lordre des appels rcursifs
Fonction qui affiche les entiers par ordre dcroissant, de n jusqu 1 :
DCROISSANT(n)
Si n = 0 alors ne rien fairesinon afficher n
DCROISSANT(n1)
Excution pour n = 2 :
-
20 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
Appel de DCROISSANT(2)Affichage de 2.Appel de DCROISSANT(1)
Affichage de 1.Appel de DCROISSANT(0)
Lalgorithme ne fait rien.Rsultat affichage dabord de 2 puis de 1 : laffichage a lieu dans lordre dcroissant.Intervertissons maintenant lordre de laffichage et de lappel rcursif :
CROISSANT(n)
Si n = 0 alors ne rien fairesinon CROISSANT(n1)
afficher n
Excution pour n = 2 :Appel de CROISSANT(2)
Appel de CROISSANT(1)Appel de CROISSANT(0)
Lalgorithme ne fait rien.Affichage de 1.
Affichage de 2.Rsultat affichage dabord de 1 puis de 2 : laffichage a lieu dans lordre croissant.
3.1.9 Exemple dalgorithme rcursif : les tours de Hano
Le problme
Le jeu est constitu dune plaquette de bois o sont plantes trois tiges. Sur ces tiges sont enfils des disques dediamtres tous diffrents. Les seules rgles du jeu sont que lon ne peut dplacer quun seul disque la fois, et quilest interdit de poser un disque sur un disque plus petit.
Au dbut tous les disques sont sur la tige de gauche, et la fin sur celle de droite.
Rsolution
Voir la figure 3.1.
Hypothse : on suppose que lon sait rsoudre le problmepour (n1) disques.
Principe : pour dplacer n disques de la tige A vers la tige C,on dplace les (n1) plus petits disques de la tige A vers latige B, puis on dplace le plus gros disque de la tige A versla tige C, puis on dplace les (n1) plus petits disques dela tige B vers la tige C.
Validit : il ny a pas de viol des rgles possible puisque leplus gros disque est toujours en bas dune tige et quelhypothse (de rcurrence) nous assure que nous savonsdplacer le bloc de (n 1) disques en respectant lesrgles.
FIG. 3.1 Mthode de rsolution du jeu des tours de Hano.
-
3.2. DRCURSIVATION 21
Algorithme
HANO(n, dpart, intermdiaire, destination)
Si n = 1 alors dplacer le disque suprieur de la tige dpart vers la tige destinationsinon HANO(n1, dpart, destination, intermdiaire)
dplacer le disque suprieur de la tige dpart vers la tige destinationHANO(n1, intermdiaire, dpart, destination)
Excution avec trois disques
1. Dplace un disque de la tige dpart vers la tige destination
2. Dplace un disque de la tige dpart vers la tige intermdiaire
3. Dplace un disque de la tige destination vers la tige intermdiaire
4. Dplace un disque de la tige dpart vers la tige destination
5. Dplace un disque de la tige intermdiaire vers la tige dpart
6. Dplace un disque de la tige intermdiaire vers la tige destination
7. Dplace un disque de la tige dpart vers la tige destination
Il ne faut pas chercher comprendre comment a marche, mais pourquoi a marche...
Complexit
On compte le nombre de dplacements de disques effectus par lalgorithme HANO invoqu sur n disques.
C(n) ={
1 si n = 1C(n1)+ 1 +C(n1) sinon =
{1 si n = 1
1 + 2C(n1) sinon
do lon en dduit que C(n) = 2n1. On a donc ici un algorithme de complexit exponentielle.
3.2 Drcursivation
Drcursiver, cest transformer un algorithme rcursif en un algorithme quivalent ne contenant pas dappels r-cursifs.
3.2.1 Rcursivit terminale
Dfinition 5 (Rcursivit terminale). Un algorithme est dit rcursif terminal sil ne contient aucun traitement aprsun appel rcursif.
Exemple :
ALGORITHME P(U)
si C alors D;P((U))sinon T
o : U est la liste des paramtres ; C est une condition portant sur U ; D est le traitement de base de lalgorithme (dpendant de U) ; (U) reprsente la transformation des paramtres ; T est le traitement de terminaison (dpendant de U).Avec ces notations, lalgorithme P quivaut lalgorithme suivant :
-
22 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
ALGORITHME P(U)
tant que C faire D;U (U)T
Lalgorithme P est une version drcursive de lalgorithme P.
3.2.2 Rcursivit non terminale
Ici, pour pouvoir drcursiver, il va falloir sauvegarder le contexte de lappel rcursif, typiquement les paramtresde lappel engendrant lappel rcursif. Originellement, lalgorithme est :
ALGORITHME Q(U)
si C(U) alors D(U);Q((U));F(U)sinon T (U)
Les piles sont des structures de stockage (via les primitives empiler et dpiler) qui fonctionnent sur le principe le dernier entr est le premier sorti (cf. chapitre 5). Les compilateurs utilisent des piles pour stocker les paramtresdes appels de fonctions, et en particulier lors de la transcription des fonctions rcursives. Nous mimons ici lutilisationdes piles pour drcursiver lalgorithme.
Aprs drcursivation on obtiendra donc :
ALGORITHME Q(U)
empiler(nouvel_appel, U)tant que pile non vide faire
dpiler(tat, V )si tat = nouvel_appel alors U V
si C(U) alors D(U)empiler(fin, U)empiler(nouvel_appel, (U))
sinon T (U)si tat = fin alors U V
F(U)
Illustration de la drcursivation de lalgorithme Q
Exemple dexcution de Q :
Appel Q(U0)C(U0) vraiD(U0)Appel Q((U0))
C((U0)) vraiD((U0))Appel Q(((U0)))
C(((U0))) fauxT (((U0)))
F((U0))F(U0)
Lexcution correspondante de Q est prsente figure 3.2. Les instructions de gestion de piles y figurent en italic,et les instructions de lalgorithme originel (ce qui nous importe) y figurent en gras.
-
3.3. DIVISER POUR RGNER 23
Appel Q(U0)empiler(nouvel_appel, U))pile = [(nouvel_appel, U0)]dpiler(tat, V ))tat nouvel_appel ; V U0 ; pile = []
U U0C(U0) vraiD(U0)empiler(fin, U))pile = [(fin, U0)]empiler(nouvel_appel, (U)))pile = [(fin, U0) ; (nouvel_appel, (U0))]
dpiler(tat, V ))tat nouvel_appel ; V (U0) ; pile = [(fin, U0)]
U (U0)C((U0)) vraiD((U0))empiler(fin, U))pile = [(fin, U0) ; (fin, (U0))]empiler(nouvel_appel, (U)))pile = [(fin, U0) ; (fin, (U0)) ; (nouvel_appel, ((U0)))]
dpiler(tat, V ))tat nouvel_appel ; V ((U0)) ; pile = [(fin, U0) ; (fin, (U0))]
U ((U0))C(((U0))) fauxT(((U0)))
dpiler(tat, V ))tat fin ; V (U0) ; pile = [(fin, U0)]
F((U0))dpiler(tat, V ))tat fin ; V U0 ; pile = []
F(U0)
FIG. 3.2 Exemple dexcution de lalgorithme drcursiv.
3.2.3 Remarques
Les programmes itratifs sont souvent plus efficaces, mais les programmes rcursifs sont plus faciles crire. Lescompilateurs savent, la plupart du temps, reconnatre les appels rcursifs terminaux, et ceux-ci nengendrent pas desurcot par rapport la version itrative du mme programme.
Il est toujours possible de drcursiver un algorithme rcursif.
3.3 Diviser pour rgner
3.3.1 Principe
Nombres dalgorithmes ont une structure rcursive : pour rsoudre un problme donn, ils sappellent eux-mmesrcursivement une ou plusieurs fois sur des problmes trs similaires, mais de tailles moindres, rsolvent les sous-problmes de manire rcursive puis combinent les rsultats pour trouver une solution au problme initial.
Le paradigme diviser pour rgner donne lieu trois tapes chaque niveau de rcursivit :
Diviser : le problme en un certain nombre de sous-problmes ;
-
24 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
Rgner : sur les sous-problmes en les rsolvant rcursivement ou, si la taille dun sous-problme est assez rduite,le rsoudre directement ;
Combiner : les solutions des sous-problmes en une solution complte du problme initial.
3.3.2 Premier exemple : multiplication nave de matrices
Nous nous intressons ici la multiplication de matrices carrs de taille n.
Algorithme naf
Lalgorithme classique est le suivant :
MULTIPLIER-MATRICES(A, B)
Soit n la taille des matrices carrs A et BSoit C une matrice carr de taille nPour i 1 n faire
Pour j 1 n faireci, j 0Pour k 1 n faire
ci, j ci, j + ai,k.bk, jrenvoyer C
Cet algorithme effectue (n3) multiplications et autant dadditions.
Algorithme diviser pour rgner naf
Dans la suite nous supposerons que n est une puissance exacte de 2. Dcomposons les matrices A, B et C ensous-matrices de taille n/2n/2. Lquation C = AB peut alors se rcrire :(
r st u
)=(
a bc d
)(e gf h
).
En dveloppant cette quation, nous obtenons :
r = ae + b f , s = ag + bh, t = ce + d f et u = cg + dh.
Chacune de ces quatre oprations correspond deux multiplications de matrices carrs de taille n/2 et une additionde telles matrices. partir de ces quations on peut aisment driver un algorithme diviser pour rgner dont lacomplexit est donne par la rcurrence :
T (n) = 8T (n/2)+ (n2),
laddition des matrices carrs de taille n/2 tant en (n2).
3.3.3 Analyse des algorithmes diviser pour rgner
Lorsquun algorithme contient un appel rcursif lui-mme, son temps dexcution peut souvent tre dcrit parune quation de rcurrence qui dcrit le temps dexcution global pour un problme de taille n en fonction du tempsdexcution pour des entres de taille moindre.
La rcurrence dfinissant le temps dexcution dun algorithme diviser pour rgner se dcompose suivant lestrois tapes du paradigme de base :
1. Si la taille du problme est suffisamment rduite, n c pour une certaine constante c, la rsolution est directe etconsomme un temps constant (1).
2. Sinon, on divise le problme en a sous-problmes chacun de taille 1/b de la taille du problme initial. Le tempsdexcution total se dcompose alors en trois parties :
-
3.3. DIVISER POUR RGNER 25
(a) D(n) : le temps ncessaire la division du problme en sous-problmes.
(b) aT (n/b) : le temps de rsolution des a sous-problmes.
(c) C(n) : le temps ncessaire pour construire la solution finale partir des solutions aux sous-problmes.
La relation de rcurrence prend alors la forme :
T (n) ={
(1) si n c,aT (n/b)+ D(n)+C(n) sinon,
o lon interprte n/b soit comme bn/bc, soit comme dn/be.
3.3.4 Rsolution des rcurrences
Thorme 1 (Rsolution des rcurrences diviser pour rgner ).Soient a 1 et b> 1 deux constantes, soit f (n) une fonction et soit T (n) une fonction dfinie pour les entiers positifspar la rcurrence :
T (n) = aT (n/b)+ f (n),
o lon interprte n/b soit comme bn/bc, soit comme dn/be.T (n) peut alors tre borne asymptotiquement comme suit :
1. Si f (n) = O(n(logb a)) pour une certaine constante > 0, alors T (n) = (nlogb a).
2. Si f (n) = (nlogb a), alors T (n) = (nlogb a logn).
3. Si f (n) = (n(logb a)+) pour une certaine constante > 0, et si a f (n/b) c f (n) pour une constante c< 1 et nsuffisamment grand, alors T (n) = ( f (n)).
Remarques :
1. Le remplacement des termes T (n/b) par T (bn/bc) ou T (dn/be) naffecte pas le comportement asymptotique dela rcurrence [2, section 4.4.2]. On omettra donc en gnral les parties entires.
2. Le thorme 1 ne couvre pas toutes les possibilit pour f (n). Par exemple, il y a un trou entre les cas 1 et 2quand f (n) est plus petite que nlogb a, mais pas polynomialement. Dans un tel cas, on ne peut tout simplementpas appliquer le thorme 1.
Retour sur le premier exemple
Utilisons le thorme 1 pour calculer la complexit de notre algorithme de multiplication de matrices diviserpour rgner naf. Ici, a = 8, b = 2 et f (n) = (n2). Donc logb a = 3, nous nous trouvons dans le cas 1 du thorme(avec = 1), lalgorithme a une complexit en (n3) et nous navons rien gagn...
3.3.5 Deuxime exemple : algorithme de Strassen pour la multiplication de matrices
Lalgorithme de Strassen est un algorithme diviser pour rgner qui neffectue que 7 multiplications de matrices,contrairement 8 dans lalgorithme prcdent, mais qui effectue plus dadditions et de soustractions de matrices, cequi est sans consquence une addition de matrices tant gratuite par rapport au cot dune multiplication.
Complexit
La complexit de lalgorithme de Strassen est donne par la rcurrence :
T (n) = 7T (n/2)+ (n2).
En utilisant le thorme 1, nous obtenons comme complexit : T (n) = (nlog2 7) = O(n2,81).
-
26 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
Algorithme
Il se dcompose en quatre tapes :
1. Diviser les matrices A et B en matrices carrs de taille n/2.
2. Au moyen de (n2) additions et soustractions scalaires, calculer 14 matrices ( prciser) A1, ..., A7, B1, ..., B7carrs de taille n/2.
3. Calculer rcursivement les 7 produits de matrices Pi = AiBi, i [1;7].4. Calculer les sous-matrices dsires r, s, t et u en additionnant et/ou soustrayant les combinaisons idoines des
matrices Pi ad-hoc, laide de (n2) additions et soustractions scalaires.
Produits de sous-matrices
Nous supposons que chaque matrice produit Pi peut scrire sous la forme :
Pi = AiBi = (i,1a + i,2b + i,3c + i,4d).(i,1e + i,2 f + i,3g + i,4h),
o les coefficients i, j et i, j sont tous pris dans lensemble {1;0;1}. Nous supposons donc que chaque produit peuttre obtenu en additionnant et soustrayant certaines des sous-matrices de A, en additionnant et soustrayant certainesdes sous-matrices de B, et en multipliant les deux matrices ainsi obtenues.
Rcrivons lquation dfinissant r :
r = ae + b f = (a b c d)
+1 0 0 00 +1 0 00 0 0 00 0 0 0
efgh
=e f g h
abcd
+ . . .. + . .. . . .. . . .
o + reprsente +1 , . reprsente 0 et - reprsente -1 . Nous rcrivons de mme les quationsdfinissant s, t et u :
s = ag + bh =
e f g habcd
. . + .. . . +. . . .. . . .
,
t = ce + d f =
e f g habcd
. . . .. . . .+ . . .. + . .
,
u = cg + dh =
e f g habcd
. . . .. . . .. . + .. . . +
.On remarque que lon peut calculer s par s = P1 + P2 o P1 et P2 sont calcules chacune au moyen dune unique
multiplication de matrice :
P1 = A1B1 = a.(gh) = agah =
. . + . . . .. . . .. . . .
,P2 = A2B2 = (a + b).h = ah + bh =
. . . +
. . . +
. . . .
. . . .
.
-
3.3. DIVISER POUR RGNER 27
De mme la matrice t peut tre calcule par t = P3 + P4 avec :
P3 = A3B3 = (c + d).e = ce + de =
. . . .. . . .+ . . .+ . . .
,P4 = A4B4 = d.( f e) = d f de =
. . . .
. . . .
. . . . + . .
.
Pour calculer r et u on introduit une matrice P5 dfinie comme suit :
P5 = A5B5 = (a + d).(e + h) =
+ . . +. . . .. . . .+ . . +
,
et on cherche obtenir r partir de P5 :
r =
+ . . .. + . .. . . .. . . .
=
+ . . +. . . .. . . .+ . . +
+
. . .
. + . .
. . . . . .
=
+ . . +. . . .. . . .+ . . +
+
. . . .
. . . .
. . . . + . .
+
. . .
. + . .
. . . .
. .
=
+ . . +. . . .. . . .+ . . +
+
. . . .
. . . .
. . . . + . .
+
. . .
. . .
. . . .
. . . .
+
. . . .
. + . +
. . . .
. .
.
Do, en posant
P6 = A6B6 = (bd).( f + h)
. . . .. + . +. . . .. .
,
on obtient r = P5 + P4P2 + P6.
-
28 CHAPITRE 3. LA RCURSIVIT ET LE PARADIGME DIVISER POUR RGNER
De mme, on cherche obtenir u partir de P5 :
u =
. . . .. . . .. . + .. . . +
=
+ . . +. . . .. . . .+ . . +
+ . . . . . .. . + . . . .
=
+ . . +. . . .. . . .+ . . +
+
. . +
. . . .
. . . .
. . . .
+ . .. . . .. . + . . . .
=
+ . . +. . . .. . . .+ . . +
+
. . +
. . . .
. . . .
. . . .
+
. . . .
. . . . . . . . . .
+ . .. . . .+ . + .. . . .
.Do, en posant
P7 = A7B7 = (a c).(e + g) = ae + ag ce cg =
+ . + .. . . . . .. . . .
,on obtient u = P5 + P1P3P7.
Discussion
Lalgorithme de Strassen nest intressant en pratique que pour de grandes matrices (n > 45) denses (peu dl-ments non nuls).
La meilleure borne suprieure connue pour la multiplication de matrices carrs de taille n est environ en O(n2,376).La meilleure borne infrieure connue est en (n2) (il faut gnrer n2 valeurs). On ne connat donc toujours pas leniveau de difficult rel dune multiplication de matrices !
-
Chapitre 4
Algorithmes de tri
4.1 Tri par fusion
4.1.1 Principe
Lalgorithme de tri par fusion est construit suivant le paradigme diviser pour rgner :
1. Il divise la squence de n nombres trier en deux sous-squences de taille n/2.
2. Il trie rcursivement les deux sous-squences.
3. Il fusionne les deux sous-squences tries pour produire la squence complte trie.
La rcursion termine quand la sous-squence trier est de longueur 1... car une telle squence est toujours trie.
4.1.2 Algorithme
La principale action de lalgorithme de tri par fusion est justement la fusion des deux listes tries.
La fusion
Le principe de cette fusion est simple : chaque tape, on compare les lments minimaux des deux sous-listestries, le plus petit des deux tant llment minimal de lensemble on le met de ct et on recommence. On conoitainsi un algorithme FUSIONNER qui prend en entre un tableau A et trois entiers, p, q et r, tels que p q < r et telsque les tableaux A[p..q] et A[q + 1..r] soient tris. Lalgorithme est prsent figure 4.1.
Complexit de la fusion
tudions les diffrentes tapes de lalgorithme : les initialisations ont un cot constant (1) ; la boucle tant que de fusion sexcute au plus r p fois, chacune de ses itrations tant de cot constant, do
un cot total en O(r p) ; les deux boucles tant que compltant C ont une complexit respective au pire de q p + 1 et de rq, ces deux
complexits tant en O(r p) ; la recopie finale cote (r p + 1).
Par consquent, lalgorithme de fusion a une complexit en (r p).
Le tri
crire lalgorithme de tri par fusion est maintenant une trivialit (cf. figure 4.2).
29
-
30 CHAPITRE 4. ALGORITHMES DE TRI
FUSIONNER(A, p, q, r)
i pj q + 1Soit C un tableau de taille r p + 1k 1tant que i q et j r faire
si A[i]< A[ j] alors C[k] A[i]i i + 1
sinon C[k] A[ j]j j + 1
k k + 1tant que i q faire C[k] A[i]
i i + 1k k + 1
tant que j r faire C[k] A[ j]j j + 1k k + 1
pour k 1 r p + 1 faireA[p + k1]C[k]
indice servant parcourir le tableau A[p..q]indice servant parcourir le tableau A[q + 1..r]tableau temporaire dans lequel on construit le rsultatindice servant parcourir le tableau temporaireboucle de fusion
on incorpore dans C les lments de A[p..q]qui ny seraient pas encore ; sil y en a,les lments de A[q + 1..r] sont dj tous dans C
on incorpore dans C les lments de A[q + 1..r]qui ny seraient pas encore ; sil y en a,les lments de A[p..q] sont dj tous dans C
on recopie le rsultat dans le tableau originel
FIG. 4.1 Algorithme de fusion de deux sous-tableaux adjacents tris.
TRI-FUSION(A, p, r)
si p< r alors q b(p + r)/2cTRI-FUSION(A, p, q)TRI-FUSION(A, q + 1, r)FUSIONNER(A, p, q, r)
FIG. 4.2 Algorithme de tri par fusion.
4.1.3 Complexit
Pour dterminer la formule de rcurrence qui nous donnera la complexit de lalgorithme TRI-FUSION, noustudions les trois phases de cet algorithme diviser pour rgner :
Diviser : cette tape se rduit au calcul du milieu de lintervalle [p;r], sa complexit est donc en (1).Rgner : lalgorithme rsout rcursivement deux sous-problmes de tailles respectives n2 , do une complexit en
2T ( n2 ).
Combiner : la complexit de cette tape est celle de lalgorithme de fusion qui est de (n) pour la construction duntableau solution de taille n.
Par consquent, la complexit du tri par fusion est donne par la rcurrence :
T (n) ={
(1) si n = 1,2T ( n2 )+ (n) sinon.
Pour dterminer la complexit du tri par fusion, nous utilisons de nouveau le thorme 1. Ici a = 2 et b = 2, donclogb a = 1 et nous nous trouvons dans le deuxime cas du thorme : f (n) = (nlogb a) = (n). Par consquent :
T (n) = (n logn).
Pour des valeurs de n suffisamment grandes, le tri par fusion avec son temps dexcution en (n logn) est nettementplus efficace que le tri par insertion dont le temps dexcution est en (n2).
-
4.2. TRI PAR TAS 31
4.2 Tri par tas
4.2.1 Dfinition dun tas
Dfinition 6 (Tas). Un tas est un arbre binaire parfait dont tous les niveaux sont complets sauf le dernier qui estrempli de la gauche vers la droite. Dans un tas, un pre est toujours plus grand que ses deux fils.
Pour un exemple de tas, voir la figure 4.3.Les tas sont gnralement reprsents et manipuls sous la forme dun tableau : Un tableau A qui reprsente un tas est un objet deux attributs :
1. longueur(A) qui est le nombre dlments qui peuvent tre stocks dans le tableau A ;
2. taille(A) qui est le nombre dlments stocks dans le tableau A.
La racine est stocke dans la premire case du tableau A[1]. Les lments de larbre sont rangs dans lordre, niveau par niveau, et de gauche droite. Les fonctions daccs
aux lments du tableau sont alors :
PRE(i)
renvoyer bi/2c
FILS-GAUCHE(i)
renvoyer 2i
FILS-DROIT(i)
renvoyer 2i + 1
Proprit des tas : A[PRE(i)] A[i].
16 14 10 8 7 9 3 2 4 11 2 3 4 5 6 7 8 9 10
FIG. 4.3 Un tas vu comme un arbre binaire ( gauche) et comme un tableau ( droite). Le nombre lintrieur dunnud de larbre est la valeur contenue dans ce nud ; le nombre au-dessus est lindice correspondant dans le tableau.
4.2.2 Conservation de la structure de tas
Lalgorithme ENTASSER (cf. figure 4.4) prend en entre un tableau A et un indice i. On suppose que les sous-arbresde racines GAUCHE(i) et DROIT(i) sont des tas. Par contre, il est possible que A[i] soit plus petit que ses fils (violantainsi la proprit de tas). ENTASSER doit faire descendre la valeur de A[i] de sorte que le sous-arbre de racine i soitun tas. Laction de cet algorithme est illustr par la figure 4.5.
Correction
Le rsultat de lalgorithme ENTASSER est bien un tas car : La structure de larbre nest pas modifie.
-
32 CHAPITRE 4. ALGORITHMES DE TRI
ENTASSER(A, i)
g GAUCHE(i)d DROIT(i)max isi g taille(A) et A[g]> A[max] alors max gsi d taille(A) et A[d]> A[max] alors max dsi max 6= i alors changer A[i] A[max]
ENTASSER(A, max)
FIG. 4.4 Algorithme ENTASSER
FIG. 4.5 Action de ENTASSER(A, 2) : la configuration initiale (figure gauche) viole la proprit du tas ; pour i = 2cette proprit est restaure par interversion de la cl avec celle du fils gauche (figure de droite) ; le rsultat nesttoujours pas un tas, et lappel rcursif ENTASSER(A, 4) intervertit la cl du nud i = 4 avec celle de son fils droit ; onobtient finalement le tas de la figure 4.3.
Un change de valeurs entre un pre et un fils na lieu que si la valeur du fils est suprieure celle du pre. Orla valeur du pre tait suprieure celles stockes dans ses deux arbres fils excepte la valeur ajoute larbre.La nouvelle cl de la racine est donc bien plus grande que lintgralit de celles stockes dans larbre dont elledevient la racine.
Complexit
Le temps dexcution de ENTASSER sur un arbre de taille n est en (1) plus le temps de lexcution rcursive deENTASSER sur un des deux sous-arbres, or ces deux sous-arbres ont une taille en au plus 2n3 (le pire cas survient quandla dernire range de larbre est exactement remplie moiti). Le temps dexcution de ENTASSER est donc dcrit parla rcurrence :
T (n) T(
2n3
)+ (1)
ce qui, daprs le cas 2 du thorme 1, nous donne : T (n) = (logn), car a = 1, b = 32 et logb a = 0.
4.2.3 Construction dun tas
La construction se fait simplement par utilisation successive de lalgorithme ENTASSER, comme le montre lalgo-rithme la figure 4.6.
Complexit
Premire borne : chaque appel entasser cote O(log2 n) et il y a O(n) appels de ce type. La complexit deCONSTRUIRE-TAS est donc en O(n log2 n). On peut en fait obtenir une borne plus fine.
-
4.3. TRI RAPIDE (QUICKSORT) 33
CONSTRUIRE-TAS(A, Valeurs)
taille[A] longueur[A]Pour i b longueur(A)2 c 1 faire ENTASSER(A,i)
FIG. 4.6 Algorithme CONSTRUIRE-TAS.
En effet, un tas n lments est de hauteur blog2 nc et une hauteur h il contient au maximum d n2h+1 e nuds. Deplus, lalgorithme ENTASSER requiert un temps dexcution en O(h) quand il est appel sur un tas de hauteur h. Do :
T (n) =blog2 nc
j=0
n2h+1
O(h) = O
(nblog2 nc
h=0
h2h
),
or
h=0
h2h
= 2.
Do :T (n) = O(n).
On peut donc construire un tas partir dun tableau en temps linaire.
Illustration de lalgorithme CONSTRUIRE-TAS
Voir la figure 4.7.
4.2.4 Algorithme du tri par tas
TRIER-TAS(A)
CONSTRUIRE-TAS(A)Pour i longueur(A) 2 faire
changer A[1] A[i]taille(A) taille(A)1ENTASSER(A,1)
Illustration de lalgorithme TRI-TAS
Voir la figure 4.8.
Complexit
La procdure TRIER-TAS prend un temps O(n log2 n) car lappel CONSTRUIRE-TAS prend un temps O(n) et quechacun des n1 appels ENTASSER prend un temps O(log2 n).
4.3 Tri rapide (Quicksort)
4.3.1 Principe
Le tri rapide est fond sur le paradigme diviser pour rgner , tout comme le tri fusion, il se dcompose donc entrois tapes :
-
34 CHAPITRE 4. ALGORITHMES DE TRI
FIG. 4.7 Action de CONSTRUIRE-TAS sur le tableau [4;1;3;2;16;9;10;14;8;7].
-
4.3. TRI RAPIDE (QUICKSORT) 35
i i
i i
i4
16
1
1410
3
i9
8
7
2
i i
i
FIG. 4.8 Action de TRIER-TAS sur le tableau [4;1;3;2;16;9;10;14;8;7].
-
36 CHAPITRE 4. ALGORITHMES DE TRI
Diviser : Le tableau A[p..r] est partitionn (et rarrang) en deux sous-tableaux non vides, A[p..q] et A[q + 1..r], telsque chaque lment de A[p..q] soit infrieur ou gal chaque lment de A[q + 1..r]. Lindice q est calculpendant la procdure de partitionnement.
Rgner : Les deux sous-tableaux A[p..q] et A[q + 1..r] sont tris par des appels rcursifs.
Combiner : Comme les sous-tableaux sont tris sur place, aucun travail nest ncessaire pour les recombiner, letableau A[p..r] est dj tri !
4.3.2 Algorithme
TRI-RAPIDE(A, p, r)
si p< r alors qPARTITIONNEMENT(A, p, r)TRI-RAPIDE(A, p, q)TRI-RAPIDE(A, q + 1, r)
Lappel TRI-RAPIDE(A, 1, longueur(A)) trie le tableau A. Le point principal de lalgorithme est bien videmment lepartitionnement qui rarrange le tableau A sur place :
PARTITIONNEMENT(A, p, r)
x A[p]i p1j r + 1tant que VRAI faire
rpter j j1 jusqu A[ j] xrpter i i + 1 jusqu A[i] xsi i< j alors changer A[i] A[ j]
sinon renvoyer j
Exemple de partitionnement :
1. Situation intiale :
1 2 3 4 5 6 7
4 3 6 2 1 5 7
Nous avons donc x = 4, i = 0 et j = 8.
2. On excute la boucle rpter j j1 jusqu A[ j] x et on obtient j = 5.3. On excute la boucle rpter i i + 1 jusqu A[i] x , et on obtient i = 1.4. Aprs lchange on obtient le tableau :
1 2 3 4 5 6 7
1 3 6 2 4 5 7
5. On excute la boucle rpter j j1 jusqu A[ j] x et on obtient j = 4.6. On excute la boucle rpter i i + 1 jusqu A[i] x , et on obtient i = 3.7. Aprs lchange on obtient le tableau :
1 2 4 3 5 6 7
1 3 2 6 4 5 7
8. On excute la boucle rpter j j1 jusqu A[ j] x et on obtient j = 3.9. On excute la boucle rpter i i + 1 jusqu A[i] x , et on obtient i = 3.
10. Comme i = j, lalgorithme se termine et renvoie la valeur 3 .
-
4.3. TRI RAPIDE (QUICKSORT) 37
4.3.3 Complexit
Pire cas
Le pire cas intervient quand le partitionnement produit une rgion n 1 lments et une un lment, commenous le montrerons ci-aprs. Comme le partitionnement cote (n) et que T (1) = (1), la rcurrence pour le tempsdexcution est :
T (n) = T (n1)+ (n).Do par sommation :
T (n) =n
k=1
(k) =
(n
k=1
k
)=
(n2).
Pour montrer que cette configuration est bien le pire cas, montrons que dans tous les cas T (n) = O(n2), cest--direquil existe une constante c telle que T (n) cn2. Si T (n) est la complexit au pire :
T (n) = max1qn1
(T (q)+ T (nq))+ (n),
o le paramtre q est dans lintervalle [1..n 1] puisque la procdure PARTITIONNEMENT gnre deux rgions detailles chacune au moins gale un. Do :
T (n) max1qn1
(cq2 + c(nq)2
)+ (n).
Or lexpression q2 + (n q)2 atteint son maximum lune des extrmits de lintervalle (drive ngative puis posi-tive). Do
max1qn1
(q2 +(nq)2
)= 12 +(n1)2 = n22(n1).
etT (n) cn22c(n1)+ (n) cn2,
puisque lon peut choisir la constante c assez grande pour que le terme 2c(n1) domine le terme (n). Du coup, letemps dexcution du tri rapide (dans le pire cas) est (n2).
Meilleur cas
On subodore que le meilleur cas apparat quand la procdure de partitionnement produit deux rgions de taille n2 .La rcurrence est alors :
T (n) = 2T (n2
)+ (n),
ce qui, daprs le cas 2 du thorme 1 nous donne
T (n) = (n logn).
Complexit en moyenne
On suppose que le tableau A ne contient pas deux fois le mme lment.
Version stochastique du tri rapide. Un algorithme est dit stochastique si son comportement est dtermin nonseulement par son entre mais aussi par les valeurs produites par un gnrateur de nombres alatoires. On modifie laprocdure PARTITIONNEMENT pour quelle est un comportement stochastique en utilisant une fonction HASARD(a,b) qui renvoie de manire quiprobable un entier entre les nombres a et b.
PARTITIONNEMENT-STOCHASTIQUE(A, p, r)
i HASARD(p,r)changer A[p] A[i]renvoyer PARTITIONNEMENT(A, p, r)
Le but ici est de faciliter lanalyse de lalgorithme et de minimiser linfluence des configurations pathologiques.
-
38 CHAPITRE 4. ALGORITHMES DE TRI
Analyse du partitionnement. La valeur q renvoye par PARTITIONNEMENT ne dpend que du rang de x = A[p]parmi les lments de A[p..r] (le rang dun nombre dans un ensemble tant le nombre dlments qui lui sont inf-rieurs ou gaux). Du fait de lencapsulation de PARTITIONNEMENT dans PARTITIONNEMENT-STOCHASTIQUE et delinterversion de A[p] et dun lment alatoire de A[p..r], rang(x) = i pour i = 1, 2, ..., n avec une probabilit 1n enposant n = r p + 1 (cest le nombre dlments de lintervalle [p..r]).
Ce qui nous intresse, cest la taille des partitions. Nous avons deux cas considrer :
1. rang(x) = 1. Lalgorithme PARTITIONNNEMENT sarrte alors avec i = j = 1 et la rgion infrieure de lapartition comprend lunique lment A[p] et est de taille 1.
2. rang(x) 2. Il existe alors au moins un lment (strictement) plus petit que x = A[p]. Par consquent, lorsdu passage dans la boucle tant que, lindice i sarrte la valeur i = p mais lindice j sarrte une valeurstrictement infrieure p. Un change est alors effectu et A[p] est plac dans la rgion suprieure. LorsquePARTITIONNEMENT se termine, chacun des rang(x)1 lments de la rgion infrieure de la partition eststrictement infrieur x. Ainsi pour chaque i = 1, 2, ..., n 1, la probabilit pour que la rgion infrieure ait ilment est de 1n
Rcurrence pour le cas moyen. Vu ce qui prcde, le temps moyen requis pour le tri dun tableau de longueur nvaut donc :
T (n) =1n
(T (1)+ T (n1)+
n1
q=1
(T (q)+ T (nq))
)+ (n).
Comme T (1) = (1) et T (n1) = O(n2) (vue ltude du pire cas), on a :
1n
(T (1)+ T (n1)) = 1n
((1)+ O(n2)
)= O(n),
et ce terme peut tre absorb par le terme (n) de la formule. Ainsi :
T (n) =1n
n1
q=1
(T (q)+ T (nq))+ (n) = 2n
n1
q=1
T (q)+ (n).
Rsolution de la rcurrence. On suppose par induction quil existe des constantes strictement positives a et b tellesque T (n) an logn+b. Si a et b sont tels que lhypothse est vraie pour n = 1 alors, si lon suppose lhypothse vraiejusquau rang n1, on a :
T (n) =2n
n1
q=1
T (q)+ (n) 2n
n1
k=1
(ak logk + b)+ (n) =2an
n1
k=1
k logk +2bn
(n1)+ (n).
Si lon sait que (cf. [2, P. 164]) :n1
k=1
k logk 12
n2 logn 18
n2,
on obtient :
T (n) 2an
(12
n2 logn 18
n2)
+2bn
(n1)+ (n) an logn a4
n + 2b + (n) = an logn + b +(
(n)+ b a4
n)
doT (n) an logn + b,
puisque lon peut choisir a suffisamment grand pour que a4 n domine (n)+b. On en conclut que le temps dexcutionmoyen du tri rapide est O(n logn).
-
Chapitre 5
Structures de donnes lmentaires
5.1 Introduction
En informatique, il existe plusieurs manires de reprsenter la notion mathmatique densemble. Il nexiste pas unereprsentation qui soit meilleure que les autres dans labsolu : pour un problme donn, la meilleure reprsentationsera celle qui permettra de concevoir le meilleur algorithme, cest--dire celui le plus esthtique et de moindrecomplexit. On parlera parfois densembles dynamiques car nos ensembles seront rarement figs.
Chaque lment de ces ensembles pourra comporter plusieurs champs qui peuvent tre examins ds lors quelon possde un pointeur ou une rfrence si on prfre utiliser une terminologie plus proche de Java que de Csur cet lment. Certains ensembles dynamiques supposent que lun des champs de lobjet contient une cl servantdidentifiant.
Ces ensembles supportent potentiellement tout une srie doprations : RECHERCHE(S, k) : tant donn un ensemble S et une cl k, le rsultat de cette requte est un pointeur sur un
lment de S de cl k, sil en existe un, et la valeur NIL sinon NIL tant un pointeur ou une rfrence sur rien .
INSERTION(S, x) : ajoute lensemble S llment point par x. SUPPRESSION(S, x) : supprime de lensemble S son lment point par x (si lon souhaite supprimer un lment
dont on ne connat que la cl k, il suffit de rcuprer un pointeur sur cet lment via un appel RECHERCHE(S,k)).
Si lensemble des cls, ou lensemble lui-mme, est totalement ordonn, dautres oprations sont possibles : MINIMUM(S) : renvoie llment de S de cl minimale. MAXIMUM(S) : renvoie llment de S de cl maximale. SUCCESSEUR(S, x) : renvoie, si celui-ci existe, llment de S immdiatement plus grand que llment de S
point par x, et NIL dans le cas contraire. PRDCESSEUR(S, x) : renvoie, si celui-ci existe, llment de S immdiatement plus petit que llment de S
point par x, et NIL dans le cas contraire.
5.2 Piles et files
5.2.1 Piles
Dfinition 7 (Pile). Une pile est une structure de donnes mettant en uvre le principe dernier entr, premier sorti (LIFO : Last-In, First-Out en anglais).
Llment t de lensemble par lopration SUPPRESSION est spcifi lavance (et donc cette opration neprend alors que lensemble comme argument) : llment supprim est celui le plus rcemment insr. LoprationINSERTION dans une pile est communment appele EMPILER, et lopration SUPPRESSION, DPILER. La figure 5.1montre les consquences des oprations EMPILER et DPILER sur une pile.
39
-
40 CHAPITRE 5. STRUCTURES DE DONNES LMENTAIRES
FIG. 5.1 Exemple de pile : a) initialement la pile contient les valeurs 3, 5 et 2 ; b) tat de la pile aprs loprationEMPILER(6) ; c) tat de la pile aprs lopration EMPILER(1) ; d) tat de la pile aprs lopration DPILER, qui arenvoy la valeur 1.
Il est facile dimplmenter une pile au moyen dun tableau, comme le montre la figure 5.2. La seule difficult danscette implmentation est la gestion des dbordements de pile qui interviennent quand on tente deffecteur loprationDPILER sur une pile vide et lopration EMPILER sur un tableau codant la pile qui est dj plein. Ce dernier problmenapparat pas lorsque lon implmente les piles au moyen dune structure de donnes dont la taille nest pas fixe apriori (comme une liste chane). Les algorithmes ralisant les fonctions EMPILER et DPILER, ainsi que la ncessairefonction auxiliaire PILE-VIDE, sont prsents figure 5.3.
FIG. 5.2 Implmentation dune pile par un tableau : a) tat initial de la pile ; b) nouvel tat aprs les actions EMPI-LER(7) et EMPILER(3) ; c) nouvel tat aprs lopration DPILER qui a renvoy la valeur 3.
5.2.2 Files
Dfinition 8 (File). Une file est une structure de donnes mettant en uvre le principe premier entr, premier sorti (FIFO : First-In, First-Out en anglais).
Llment t de lensemble par lopration SUPPRESSION est spcifi lavance (et donc cette opration ne prendalors que lensemble comme argument) : llment supprim est celui qui est rest le plus longtemps dans la file. Unefile se comporte exactement comme une file dattente de la vie courante. La figure 5.4 montre les consquences desoprations INSERTION et SUPPRESSION sur une file.
On peut implmenter les files au moyen de tableaux. La figure 5.5 illustre limplmentation de files n1 lmentsau moyen dun tableau n lments et de deux attributs :
tte(F) qui indexe (ou pointe) vers la tte de la file ; queue(F) qui indexe le prochain emplacement o sera insr un lment nouveau.
Les lments de la file se trouvent donc aux emplacements tte(F), tte(F)+1, ..., queue(F)-1 (modulo n). Quandtte(F) = queue(F), la liste est vide. Les algorithmes ralisant les fonctions INSERTION et SUPPRESSION, ainsi que
-
5.2. PILES ET FILES 41
PILE-VIDE(P)
si sommet(P)=0 alors renvoyer VRAIsinon renvoyer FAUX
EMPILER(P, x)
si sommet(P) = longueur(P) alors erreur dbordement positif sinon sommet(P) sommet(P)+1
P[sommet(P)] x
DPILER(P)
si PILE-VIDE(P) alors erreur dbordement ngatif sinon sommet(P) sommet(P)1
renvoyer P[sommet(P)+ 1]
FIG. 5.3 Algorithmes de manipulation des piles implmentes par des tableaux.
FIG. 5.4 Exemple de file : a) initialement la file contientles valeurs 7, 4, 8, 9, 6 et 1 (de la plus anciennement la plus rcemment insre) ; b) tat de la file aprs lop-ration INSERTION(3) ; c) tat de la file aprs loprationSUPPRESSION qui a renvoy la valeur 7.
FIG. 5.5 Implmentation dune file par un tableau : a)tat initial de la file ; b) nouvel tat aprs laction INSER-TION(7) ; d) nouvel tat aprs laction INSERTION(5) ; d)nouvel tat aprs lopration SUPPRESSION qui a ren-voy la valeur 1.
-
42 CHAPITRE 5. STRUCTURES DE DONNES LMENTAIRES
la ncessaire fonction auxiliaire FILE-VIDE, sont prsents figure 5.6. La seule difficult dans cette implmentationest la gestion des dbordements de file qui interviennent quand on tente deffectuer lopration SUPPRESSION sur unepile vide et lopration INSERTION sur un tableau codant la file qui est dj plein. Ce dernier problme napparat paslorsque lon implmente les files au moyen dune structure de donne dont la taille nest pas fixe a priori (commeune liste doublement chane).
FILE-VIDE(F)
si tte(F)=queue(F) alors renvoyer VRAIsinon renvoyer FAUX
INSERTION(F , x)
si queue(F) + 1 (modulo n) = tte(F) alors erreur dbordement positif sinon F [queue(F)] x
queue(F) queue(F)+1
SUPPRESSION(F)
si FILE-VIDE(F) alors erreur dbordement ngatif sinon tte(F) tte(F)+1
renvoyer F[tte(F)1]
FIG. 5.6 Algorithmes de manipulation des files implmentes par des tableaux.
5.3 Listes chanes
5.3.1 Dfinitions
Dfinition 9 (Liste chane). Une liste chane est une structure de donnes dans laquelle les objets sont arrangslinairement, lordre linaire tant dtermin par des pointeurs sur les lments.
Chaque lment de la liste, outre le champ cl, contient un champ successeur qui est pointeur sur llment suivantdans la liste chane. Si le champ successeur dun lment vaut NIL, cet lment na pas de successeur et est doncle dernier lment ou la queue de la liste. Le premier lment de la liste est appel la tte de la liste. Une liste L estmanipule via un pointeur vers son premier lment, que lon notera TTE(L). Si TTE(L) vaut NIL, la liste est vide.
La figure 5.7 prsente un exemple de liste chane et montre les consquences des oprations INSERTION et SUP-PRESSION sur une telle structure de donnes.
FIG. 5.7 Exemple de liste chane : a) initialement la liste chane contient les valeurs 9, 6, 4 et 1 ; b) tat de la listechane aprs lopration INSERTION(5) ; c) tat de la liste chane aprs lopration SUPPRESSION(4).
Une liste chane peut prendre plusieurs formes : Liste doublement chane : en plus du champ successeur, chaque lment contient un champ prdcesseur
qui est un pointeur sur llment prcdant dans la liste. Si le champ prdcesseur dun lment vaut NIL, cet
-
5.3. LISTES CHANES 43
lment na pas de prdcesseur et est donc le premir lment ou la tte de la liste. Une liste qui nest pasdoublement chane est dite simplement chane.La figure 5.8 prsente un exemple de liste doublement chane et montre les consquences des oprations IN-SERTION et SUPPRESSION sur une telle structure de donnes.
FIG. 5.8 Exemple de liste doublement chane : a) initialement la liste contient les valeurs 9, 6, 4 et 1 ; b) tat de laliste aprs lopration INSERTION(5) ; c) tat de la liste aprs lopration SUPPRESSION(4).
Trie ou non trie : suivant que lordre linaire des lments dans la liste correspond ou non lordre linairedes cls de ces lments.
Circulaire : si le champ prccesseur de la tte de la liste pointe sur la queue, et si le champ successeur de laqueue pointe sur la tte. La liste est alors vue comme un anneau.
5.3.2 Algorithmes de manipulation des listes chanes
Recherche
Lalgorithme RECHERCHE-LISTE(L, k) trouve le premier lment de cl k dans la liste L par une simple recherchelinaire, et retourne un pointeur sur cet lment. Si la liste ne contient aucun objet de cl k, lalgorithme renvoie NIL.
RECHERCHE-LISTE(L, k)
x TTE(L)tant que x 6= NIL et cl(x) 6= k faire
x successeur(x)renvoyer x
Cet algorithme manipule aussi bien des listes simplement que doublement que simplement chanes.
Insertion
tant donn un lment x et une liste L, lalgorithme INSERTION-LISTE insre x en tte de L.
INSERTION-LISTE(L, x)
successeur(x) TTE(L)si TTE(L) 6= NIL alors prdecesseur(TTE(L)) xTTE(L) xprdecesseur(x) NIL
Cet algorithme est crit pour les listes doublement chanes. Il suffit dignorer les deux instructions concernant lechamp prdcesseur pour obtenir lalgorithme quivalent pour les listes simplement chanes.
-
44 CHAPITRE 5. STRUCTURES DE DONNES LMENTAIRES
Suppression
Lalgorithme SUPPRESSION-LISTE limine un lment x dune liste chane L. Cet algorithme a besoin dun poin-teur sur llment x supprimer. Si on ne possde que la cl de cet lment, il faut pralablement utiliser lalgorithmeRECHERCHE-LISTE pour obtenir le pointeur ncessaire.
SUPPRESSION-LISTE(L, x)
si prdcesseur(x) 6= NILalors successeur(prdcesseur(x)) successeur(x)sinon TTE(L) successeur(x)
si successeur(x) 6= NILalors prdcesseur(successeur(x)) prdcesseur(x)
Cet algorithme est crit pour les listes doublement chanes. Lalgorithme quivalent pour les listes simplementchanes est plus compliqu puisquavec les listes simplement chanes nous navons pas de moyen simple de rcuprerun pointeur sur llment qui prcde celui supprimer...
SUPPRESSION-LISTE(L, x)
si x = TTE(L)alors TTE(L) successeur(x)sinon y TTE(L)
tant que successeur(y) 6= x faire y successeur(y)successeur(y) successeur(x)
5.3.3 Comparaison entre tableaux et listes chanes
Aucune structure de donnes nest parfaite, chacune a ses avantages et ses inconvnients. La figure 5.9 prsenteun comparatif des listes simplement chanes, doublement chanes et des tableaux, tris ou non, sur des oprationslmentaires. Les complexits indiques sont celles du pire cas. Suivant les oprations que nous aurons effectuer, etsuivant leurs frquences relatives, nous choisirons lune ou lautre de ces structures de donnes.
-
5.3. LISTES CHANES 45
liste chane liste chane liste chane liste chane tableau tableausimple simple double double
non trie trie non trie trie non tri triRECHERCHE(L, k) (n)a (n)a (n)a (n)a (1)b (1)b
(n)c (n)dINSERTION(L, x) (1) (n)e (1) (n)e ou (n)c ou
erreurf erreurf
SUPPRESSION(L, x) (n) (n) (1) (1) (n)g (n)gSUCCESSEUR(L, x) h (n)i (1) (n)i (1) (n)i (1)
PRDCESSEUR(L, x) h (n)i (n)j (n)i (1) (n)i (1)MINIMUM(L) (n)i (1) (n)i (1) (n)i (1)MAXIMUM(L) (n)i (n)k (n)i (n)k (n)i (1)
aDans le pire cas il faut parcourir tous les lments pour se rendre compte que la clef ntait pas dans lensemble.bLa cl tant lindice de llment dans le tableau.cDans le pire cas, il faut allouer un nouveau tableau et recopier tous les lments de lancien tableau dans le nouveau.dDans le pire cas, linsertion a lieu dans la premire cas du tableau, et il faut dcaler tous les lments dj prsents.eAu pire, linsertion a lieu en fin de liste.fAu cas o lon veut effectuer une insertion dans un tableau dj plein et quil nest pas possible deffectuer une allocation dynamique de tableau,
comme en FORTRAN 77 ou en PASCAL.gDans le pire cas on supprime le premier lment du tableau et il faut dcaler tous les autres lments.hAu sens de lordre sur la valeur des cls.iComplexit de la recherche du maximum (ou du minimum) dans un ensemble n lments...jComplexit de la recherche du maximum dans un ensemble n lments... car il faut entreprendre la recherche du prdcesseur depuis le dbut
de la liste.kIl faut parcourir la liste en entier pour trouver son dernier lment.
FIG. 5.9 Efficacits respectives des listes chanes et des tableaux.
-
46 CHAPITRE 5. STRUCTURES DE DONNES LMENTAIRES
-
Chapitre 6
Programmation dynamique
La programmation dynamique, comme la mthode diviser pour rgner (cf. section 3.3), rsout les problmesen combinant les solutions de sous-problmes. La programmation dynamique sapplique quand les sous-problmes nesont pas indpendants mais ont des sous-sous-problmes en commun. Dans ce cas, un algorithme diviser pour rgner fait plus de travail que ncessaire, en rsolvant plusieurs fois les sous-sous-problmes communs. Un algorithme deprogrammation dynamique rsout chaque sous-sous-problme une unique fois et mmorise sa solution dans un tableau,spargnant ainsi le recalcul de la solution chaque fois que le sous-sous-problme est rencontr.
La programmation dynamique est en gnral applique aux problmes doptimisation : ces problmes peuventadmettre plusieurs solutions, parmi lesquelles on veut choisir une solution optimale (max