ALGORITHMIQUE A L G O R I T H M I Q U E Notes du cours FS/1/6584 Année préparatoire au master 60 en informatique ULB UMH Gilles GEERAERTS (Université Libre de Bruxelles) ANNÉE ACADÉMIQUE 2008 2009 (2 E ÉDITION)
2 Le personnage en couverture est le mathématicien persan Mohamed IBN MUSSA AL- KHAWARIZMI (783? 850?) dont le nom a donné le mot français algorithme, car il en a décrit plusieurs. Le titre d un de ses ouvrages a également donné à la langue française le mot algèbre. AL-KHAWARIZMI est considéré par beaucoup comme le père de l algèbre moderne (il a d ailleurs introduit l habitude d appeller x l inconnue dans une équation). Pour autant, ses travaux ne se limitent pas à ce domaine : on lui doit d importantes contributions dans les domaines de l arithmétique, de l astronomie, ou de la géographie. Ce document a été mis en page sous LATEX 2ε.
Table des matières 1 Introduction 11 1.1 Le contenu et les objectifs du cours................... 11 1.1.1 Algorithmes, Algorithmique.................. 11 1.1.2 Les objectifs et l orientation du cours............. 14 1.2 Bibliographie.............................. 14 2 Préliminaires 15 2.1 Rappels de mathématiques....................... 15 2.1.1 Sommes et produits....................... 15 2.1.2 Plancher et plafond....................... 16 2.2 Le pseudo-langage........................... 16 2.2.1 Types et variables........................ 17 2.2.2 Instructions........................... 17 2.2.3 Gestion de la mémoire..................... 18 3 Itération, induction, récursivité 21 3.1 Itération et induction.......................... 22 3.1.1 Raisonnement par induction.................. 24 3.2 Preuves de programmes......................... 27 3.2.1 Notion d invariant de boucle.................. 28 3.2.2 Un exemple de preuve par invariant.............. 29 3.3 Récursivité............................... 31 3.3.1 Récursivité et induction.................... 32 3.3.2 Fonctions récursives...................... 33 4 La complexité algorithmique 35 4.1 Introduction............................... 35 4.2 Notion d efficacité........................... 35 4.2.1 Mesure du temps de calcul................... 36 4.2.2 Compter le nombre d étapes.................. 37 4.3 La notion de grand O.......................... 39 4.3.1 Intuition............................. 39 4.3.2 Définition formelle....................... 40 4.3.3 Classes de complexité algorithmique.............. 42 4.3.4 Règles de combinaison et de simplification.......... 42 4.4 Le cas des programmes récursifs.................... 44 4.4.1 Utilisation de l induction.................... 45 3
4 TABLE DES MATIÈRES 5 Les listes 49 5.1 Motivation : critique des tableaux.................... 49 5.2 Les listes simplement liées....................... 50 5.2.1 Comparaison aux tableaux................... 52 5.2.2 Algorithmes.......................... 53 5.2.3 Listes triées........................... 57 5.3 Les listes circulaires avec élément pré-tête............... 60 5.3.1 Différences par rapport aux listes «simples»......... 60 5.3.2 Algorithmes.......................... 63 5.4 Les listes doublement liées....................... 68 5.5 Implémentation des listes dans les vecteurs.............. 70 5.5.1 Application........................... 71 5.6 Vue récursive.............................. 74 5.6.1 Algorithmes.......................... 76 6 Les piles et les files 79 6.1 Les piles................................. 79 6.1.1 Implémentation dans une liste................. 80 6.1.2 Implémentation dans un vecteur................ 81 6.2 Les files................................. 83 6.2.1 Implémentation dans une liste................. 85 6.2.2 Implémentation dans un vecteur................ 87 6.3 Applications............................... 90 6.3.1 Vérification des parenthèses.................. 92 6.3.2 Évaluation d une expression en notation postfixée....... 93 7 Les arbres 97 7.1 Introduction............................... 97 7.1.1 Définitions........................... 98 7.1.2 Vocabulaire........................... 99 7.1.3 Cas particuliers......................... 102 7.1.4 Implémentation......................... 105 7.1.5 Application : les arbres d expressions............. 106 7.2 Parcours des arbres binaires....................... 109 7.2.1 Parcours préfixé ou parcours en profondeur.......... 110 7.2.2 Parcours infixe......................... 115 7.2.3 Parcours postfixé........................ 115 7.2.4 Le parcours par niveaux ou parcours en largeur........ 116 7.2.5 Applications des parcours................... 118 8 Algorithmes de recherche 121 8.1 Introduction............................... 121 8.2 Données stockées dans des vecteurs.................. 122 8.2.1 Recherche linéaire simple................... 122 8.2.2 Recherche linéaire dans un vecteur trié............ 123 8.2.3 Recherche dichotomique dans un vecteur trié......... 125 8.2.4 Tables de hachage....................... 130 8.3 Données stockées dans des listes.................... 131 8.4 Données stockées dans des arbres................... 132 8.4.1 Parcours simple......................... 132
TABLE DES MATIÈRES 5 8.4.2 Arbres binaires de recherche.................. 133 9 Conclusion : aux limites de l algorithmique 147
6 TABLE DES MATIÈRES
Table des figures 1.1 Une illustration du tri par sélection................... 13 1.2 Une illustration de la méthodologie du cours.............. 14 3.1 L ordinogramme de la boucle tant que................. 24 4.1 Comparaison de polynômes de degrés 3 et 4 (petite échelle)...... 40 4.2 Comparaison de polynômes de degrés 3 et 4 (grande échelle)...... 41 4.3 Comparaison de différentes fonctions caractérisant les principales classes de complexité algorithmique...................... 42 4.4 Une illustration de l exécution de Facto(k)............... 47 5.1 Un exemple de liste........................... 51 5.2 Un exemple de suppression dans une liste simplement liée...... 52 5.3 Un exemple d insertion dans une liste simplement liée......... 52 5.4 Un exemple de déplacement d un élément dans une liste simplement liée 53 5.5 Un exemple de liste circulaire avec élément pré-tête.......... 62 5.6 Un exemple d insertion en tête dans une liste circulaire avec élément pré-tête.................................. 63 5.7 Une liste circulaire avec élément pré-tête vide.............. 63 5.8 Illustration de la recherche d une information dans une liste circulaire avec élément pré-tête.......................... 64 5.9 Un exemple de liste doublement liée................... 68 5.10 Un exemple d insertion dans une liste doublement liée........ 69 5.11 Un exemple de liste implémentée dans un vecteur, et son équivalent utilisant des pointeurs.......................... 71 6.1 Exemple de pile............................. 80 6.2 La pile de la Fig. 6.1 implémentée dans une liste............ 81 6.3 Exemple de manipulation de file dans un vecteur........... 89 6.4 Vecteur implémentant une file vu comme un vecteur circulaire.... 90 7.1 Exemple d arbre............................. 98 7.2 Exemple d arbre............................. 99 7.3 La vue récursive de l arbre de la Fig. 7.2................ 100 7.4 Quelques illustrations du vocabulaire sur les arbres........... 101 7.5 Un exemple d arbre binaire équilibré.................. 102 7.6 Un exemple d arbre d expression qui représente (3 + 5) 2....... 109 7.7 Les quatre parcours d arbre classiques.................. 111 7.8 Illustration du parcours en largeur................... 117 7
8 TABLE DES FIGURES 8.1 Illustration de la recherche dichotomique................ 126 8.2 Exemple d arbre binaire de recherche (équilibré)........... 134 8.3 L ordre sur les nœuds induit par un arbre binaire de recherche..... 135 8.4 Exemples d insertion dans un ABR................... 137 8.5 Illustration des trois cas de suppression dans un ABR......... 140 8.6 Le détachement du maximum dans un ABR.............. 142 8.7 Exemple d arbre dont la hauteur est en O du nombre de nœuds.... 146
10 TABLE DES FIGURES
Chapitre 1 Introduction 1.1 Le contenu et les objectifs du cours 1.1.1 Algorithmes, Algorithmique Pour expliquer ce que sont les ordinateurs, il est de coutume de les comparer aux calculatrices de bureau, et d expliquer que, somme toute, un ordinateur n est rien d autre qu une calculatrice très perfectionnée. Il y a pourtant une différence importante entre une calculatrice capable d effectuer les quatre opérations de base et un ordinateur : c est que l ordinateur est, par définition, programmable, ce qui n est le cas que des modèles les plus évolués de calculatrices... Cette différence est fondamentale. Alors qu une calculatrice ne donne accès qu aux fonctionnalités qui sont liées à chacune de ses touches, l ordinateur offre un jeu d instructions de base très riche, dont l utilisateur peut se servir à sa guise afin d élaborer des programmes capables de résoudre des problèmes bien plus complexes que ceux traités par les instructions de base. L immense majorité du travail effectué par un professionnel de l informatique touche donc de près ou de loin à la question suivante : «Comment faire résoudre tel problème à un ordinateur?» Une part de la réponse à cette question est parfois trouvée dans l assemblage de solutions préexistantes fournies par des tierces parties. Néanmoins, tout informaticien se retrouve confronté un jour ou l autre à la nécessité de programmer une nouvelle fonctionnalité, soit pour résoudre le problème posé dans son entièreté, soit comme étape particulière d une solution globale dont certaines étapes sont déjà fournies. La tâche de l informaticien consiste alors, grosso modo à traduire des desiderata exprimés de façon plus ou moins claire et plus ou moins formelle en un programme écrit dans un langage de programmation déterminé. Un exemple de desiderata pourrait être : «Trier un tableau de nombres entiers par ordre croissant». Dans ce cas, il y aura lieu, dans un premier temps, d établir la méthode générale qui va être appliquée. Par exemple : 1. Rechercher dans tout le tableau la valeur minimale. 2. Placer cette valeur minimale en première position, et placer la valeur qui était en première position là où était la valeur minimale (en d autres mots : échanger les deux valeurs). La valeur minimale est maintenant «à sa place» 11
12 CHAPITRE 1. INTRODUCTION 3. Recommencer le même traitement sur la partie du tableau contenant les éléments qui ne sont pas encore à leur place, et ce, tant qu il y en a. Cette méthode est illustrée à la Fig. 1.1. Nous l appellerons tri par sélection, car à chaque étape nous sélectionnons l élément à placer en tête du tableau, Elle semble satisfaisante, et peut donc être traduite dans le langage de programmation choisi. Il est intéressant de remarquer que nous avons introduit une étape intermédiaire entre la compréhension du problème et sa résolution en terme de programme informatique. Cette étape a consisté en la description d une méthode générale de tri, qui exprime l essence du programme à produire, et qui aurait d ailleurs pu être traduite dans plusieurs langages de programmation différents. Cette méthode est ce que nous appelons un algorithme, c est-à-dire une suite d actions bien définies à enchaîner pour résoudre un problème. Remarquons que tout programme est, lui aussi, un algorithme. Néanmoins, nous verrons dans la suite qu il est souvent pratique d adopter une description abstraite des algorithmes qui ignore les détails d implémentation liés à un langage particulier. Ce choix, que nous ferrons dans le cadre de ce cours, nous permettra souvent de tenir des raisonnements formels et rigoureux sur l algorithme choisi. En pratique, nous exprimerons les algorithmes étudiés à l aide d un pseudo-langage de programmation, qui est décrit au Chapitre 2. La méthodologie que nous venons d esquisser est résumée à la Fig. 1.2. Dans ce cadre, la phase de conception de l algorithme est l étape essentielle, car c est à travers l algorithme qu on spécifie l idée du traitement à réaliser. Cela ne veut pas dire pour autant que la phase de traduction en programme est facile ou triviale : elle connaît ses problèmes spécifiques, mais nous ne les aborderons pas ici. Au contraire, nous allons nous concentrer sur l étude de l algorithmique, c est-à-dire la discipline qui étudie les algorithmes et leur conception. Pour autant, il ne faut pas confondre l algorithmique avec une liste de solutions préétablies pour chaque problème, un peu comme un bon livre de cuisine offre une recette adaptée à chaque circonstance. En effet, la méthode décrite ci-dessus peut soulever certaines questions comme : 1. Cette méthode est-elle correcte? Autrement dit, est-on sûr qu en l appliquant à n importe quel tableau, on obtiendra toujours un tableau trié? Afin de nous en convaincre le mieux possible, une preuve formelle et rigoureuse est nécessaire. Le concept de correction d un algorithme et les méthodes pour la prouver seront introduits au Chapitre 3. 2. La méthode utilisée consiste en la répétition d un même traitement. Est-il possible d utiliser d autres «canevas» d algorithme? Nous étudierons notamment la récursivité au Chapitre 3. 3. Quelle est l efficacité de la méthode utilisée? Comment peut-on la mesurer? Comment peut-on comparer deux méthodes différentes résolvant le même problème afin de sélectionner la plus efficace? Nous apporterons des réponses à ces questions au Chapitre 4. Par ailleurs, l algorithmique est étroitement liée à l étude des structures de données. Dans l exemple de cette introduction, la structure de données est précisée explicitement : c est un tableau d entiers. On peut dès lors se demander si on n aurait pas obtenu un algorithme de tri plus efficace si on avait structuré les données autrement. Par ailleurs, la structure de tableau n est pas forcément adaptée à tous les problèmes.
1.1. LE CONTENU ET LES OBJECTIFS DU COURS 13 7 5 9 1 4 1 5 9 7 4 1 4 9 7 5 1 4 5 7 9 1 4 5 7 9 1 4 5 7 9 FIG. 1.1 Une illustration du tri par sélection. Les cases grisées sont celles qui sont considérées en place.
14 CHAPITRE 1. INTRODUCTION Français ou autre langue naturelle { Problème et desiderata Pseudo-langage { Algorithme Formulation des hypothèses et réflexion sur le problème Permet de raisonner formellement: Preuve de correction, etc... Traduction vers le langage choisi Langage de Programmation { Programme FIG. 1.2 Une illustration de la méthodologie que nous adopterons dans le cours. Dans les chapitres 5, 6 et 7 nous étudierons d autres structures de données ainsi que leurs algorithmes associés. 1.1.2 Les objectifs et l orientation du cours Ce cours adopte une approche scientifique de l algorithmique. Cela signifie qu on y enseignera des algorithmes et des structures de données de base qui permettent de résoudre des problèmes typiques, mais aussi des outils (comme la complexité, les invariants) qui permettent d analyser ces solutions, de les justifier, de mieux les comprendre, et d en élaborer de nouvelles. Ce cours fera donc appel tant à la rigueur qu à la créativité des étudiants. 1.2 Bibliographie Ce cours se base en grande partie sur les premiers chapitres du livre Foundations of Computer Science, A. Aho, J. Ullman, Computer Science Press, New York, 1992. Cet excellent ouvrage aborde différents aspects fondamentaux de l informatique, avec une approche résolument scientifique. Néanmoins, il va au-delà du contenu de ce cours car il aborde aussi les graphes ou la logique. Il en existe différentes versions dans lesquelles les algorithmes sont présentés soit en C, soit en Pascal. Une traduction française est publiée chez Dunod sous le titre Concepts fondamentaux de l informatique. L ouvrage Introduction to algorithms 2 e ed., T. Cormen, C. Leiserson, R. Rivest, C. Stein, MIT Press, 2001 est considérée par beaucoup comme la référence en matière d algorithmes. Le sujet est traité en profondeur, et, à nouveau, avec beaucoup de rigueur. Une traduction en français existe également sous le titre Introduction à l algorithmique, chez Dunod (ISBN 9782100039227). D autres références sont données dans la bibliographie, à la fin du présent volume.