CER SCHMITT Mathieu Prosit aller : Quelle galère Objectifs : - Savoir manipuler des données avec les Algorithmes Définition des mots-clés : - Algorithme : On désigne par algorithmique ou algorithmie l’ensemble des activités logiques qui relèvent des algorithmes. Dans le cas général, l’algorithmique s’effectue au moyen de calculs. - Classeur : Un classeur en informatique permet de classer des donner. Par exemple, sous Excel, un classeur permet d’effectuer des opérations comme classement, tri,… - Algorithme de Tri : En informatique ou en mathématiques, un algorithme de tri est un algorithme qui permet d'organiser une collection d'objets selon un ordre déterminé. Les objets à trier font donc partie d'un ensemble muni d'une relation d'ordre (de manière générale un ordre total). Les ordres les plus utilisés sont l’ordre numérique et l'ordre lexicographique (dictionnaire). Algo. Tri/Recherche Page 1 CER SCHMITT Mathieu - Automate : Dans le domaine de l'informatique ou des graphes, on nomme automate une machine à traiter de l'information qui se caractérise par : o o différents états un système de transition d'états qui absorbe soit des caractères, soit des entités syntaxiques d'ordre supérieur (variable, entier, flottant, etc.) On peut définir les automates par des modèles formels (voir aussi : automate fini, automate à pile, machine de Turing). La grande relation entre l'automate et l'informatique c'est d'avoir créé une intelligence artificielle et cette dernière c'est l'ensemble des programmes informatiques existants. - Programme informatique : Un programme informatique est une succession d'instructions exécutable par l'ordinateur. Toutefois, l'ordinateur ne sait manipuler que du binaire, c'est-à-dire une succession de 0 et de 1. Il est donc nécessaire d'utiliser un langage de programmation pour écrire de façon lisible, c'est-à-dire avec des instructions compréhensibles par l'humain car proches de son langage, les instructions à exécuter par l'ordinateur. - Données : Informations utilisées par un logiciel. Elles peuvent être créées par l'utilisateur ou par le programme lui-même. Axes de recherche : Etudier les algorithmes de trie et leurs contextes Permuter deux valeurs Pour trier les valeurs d'un tableau, il va être nécessaire de permuter les valeurs contenues dans les différentes cases du tableau. Pour cela, une fonction de permutation, qui sera appelée "echanger", doit être écrite. Cette fonction prend en argument un tableau et deux entiers i et j. Elle récupère la valeur contenue dans la iième case du tableau, affecte à cette case la valeur contenue dans la jième case, puis affecte à la jième case l'ancienne valeur de la iième case. Algo. Tri/Recherche Page 2 CER SCHMITT Mathieu Exemple : Considérons le tableau T suivant [1;4;3;2;5] dans lequel la permutation des valeurs contenues dans la première et la troisième case va être effectuée (la première case du tableau portant l'indice 0). Soit i=1 et j=3. Etape 1 : Mémorisation de la valeur contenue dans la case i=1 : M=T(i)=T(1)=4 Etape 2 : Affectation à la iième case de la valeur de la jième case: T(i)=T(j)=T(3)=2. Soit T=[1;2;3;2;5] Etape 4 : Affectation à la jième case de la valeur contenue dans la mémoire M : T(j)=M. Soit T=[1;2;3;4;5] C'est ce qu'il fallait obtenir. Code source : Algorithme de permutation échanger(tableau T, entier i, entier j) début entier M M<-T(i) T(i)<-T(j) T(j)<-M fin Le tri à bulle L'algorithme du tri bulle - ou bubble sort - consiste à regarder les différentes valeurs adjacentes d'un tableau, et à les permuter si le premier des deux éléments est supérieur au second. L'algorithme se déroule ainsi : les deux premiers éléments du tableau sont comparés, si le premier élément est supérieur au second, une permutation est effectuée. Ensuite, sont comparés et éventuellement permutés les valeurs 2 et 3, 3et 4 jusque (n-1) et n. Une fois cette étape achevée, il est certain que le dernier élément du tableau est le plus grand. L'algorithme reprend donc pour classer les (n-1) éléments qui précédent. L'algorithme se termine quand il n'y a plus de permutations possibles. Pour classer les n valeurs du tableau, il faut, au pire, effectuer l'algorithme n fois. Cet algorithme porte le nom de tri bulle car, petit à petit, les plus grands éléments du tableau remontent, par le jeu des permutations, en fin de tableau. Dans un aquarium il en va de même : les plus grosses bulles remontent plus rapidement à la surface que les petites qui restent collés au fond. Algo. Tri/Recherche Page 3 CER SCHMITT Mathieu Exemple : Evolution du tableau au fil de l'algorithme (en bleu, les éléments qui sont comparés, et éventuellement permutés, pour passer à la ligne suivante). Code source : Algorithme de tri à bulle tri_bulle(tableau T) debut entier longueur, i booleen inversion longueur<-taille(T) faire inversion=faux pour i=0 à (longueur-1) si T(i)>T(i+1) echanger(T,i,i+1) inversion<-vrai fin si fin pour tantque inversion fin Algo. Tri/Recherche Page 4 CER SCHMITT Mathieu Tri par sélection Le tri par sélection est l'un des tris les plus instinctifs. Le principe est que pour classer n valeurs, il faut rechercher la plus grande valeur et la placer en fin de liste, puis la plus grande valeur dans les valeurs restante et la placer en avant dernière position et ainsi de suite... Considérons un tableau à n éléments. Pour effectuer le tri par sélection, il faut rechercher dans ce tableau la position du plus grand élément. Le plus grand élément est alors échangé avec le dernier élément du tableau. Ensuite, on réitère l'algorithme sur le tableau constitué par les (n-p) premiers éléments où p est le nombre de fois où l'algorithme a été itéré. L'algorithme se termine quand p=(n1), c'est à dire quand il n'y a plus qu'une valeur à sélectionner ; celle ci est alors la plus petite valeur du tableau. Exemple Grandes étapes de l'évolution du tableau au fil de l'algorithme. En bleu, les valeurs déja traitées. Algo. Tri/Recherche Page 5 CER SCHMITT Mathieu Algorithme de tri par séléction tri_selection(tableau T) debut entier longueur, maxi, i longueur<-taille(T) tantque(longueur>0) faire //recherche de la position du plus grand élément dans le tableau non encore trié maxi<-0; pour i de 1 à (longueur-1) faire si T(i)>T(maxi) alors maxi<-i fin si fin pour //echange du plus grand élément avec le dernier echanger(T,maxi,longueur-1) //traitement du reste du tableau longueur<-longueur-1 fin tantque fin Algo. Tri/Recherche Page 6 CER SCHMITT Mathieu Tri par insertion Le tri par insertion est un autre algorithme que l'on peut qualifier de naïf. Cet algorithme consiste à piocher une à une les valeurs du tableau et à les insérer, au bon endroit, dans le tableau trié constitué des valeurs précédemment piochées et triées. Les valeurs sont piochées dans l'ordre où elles apparaissent dans le tableau. Soit p l'indice de la valeur piochée, les (p-1) premières valeurs du tableau constituent le tableau trié dans lequel va être inséré la pième valeur. Au début de l'algorithme, il faut considérer que la liste constituée du seul premier élément est trié : c'est vrai puisque cette liste ne comporte qu'un seul élément. Ensuite, on insère le second élément (p=2), puis le troisième (p=3) etc. Ainsi, p varie de 2 à n, où n est le nombre total d'éléments du tableau. Le problème de cet algorithme est qu'il faut parcourir le tableau trié pour savoir à quel endroit insérer le nouvel élément, puis décaler d'une case toutes les valeurs supérieures à l'élément à insérer. En pratique, le tableau classé est parcouru de droite à gauche, c'est à dire dans l'ordre décroissant. Les éléments sont donc décalés vers la droite tant que l'élément à insérer est plus petit qu'eux.. Dés que l'élément à insérer est plus grand qu'un des éléments du tableau triée il n'y a plus de décalage, et l'élément est inséré dans la case laissée vacante par les éléments qui ont été décalés. Exemple : Grandes étapes de l'évolution du tableau au fil de l'algorithme. En bleu, le tableau trié, en rouge, la valeur de la mémoire qui contient la valeur à insérer. Algo. Tri/Recherche Page 7 CER SCHMITT Mathieu Pseudo-code : Algorithme de Tri par insertion tri_insertion(tableau T) debut entier longueur, i, memoire, compteur; booleen marqueur; longueur<-taille(T) pour i=1 à (longueur-1) faire memoire<-T(i) //valeur à insérer au tour i compteur<-(i-1) faire marqueur=faux //on n'a pas fait de décalage si T(compteur)>memoire alors T(compteur+1)<-T(compteur) //décalage des plus grandes valeurs du tableau compteur<-compteur-1 marqueur=vrai //on vient de faire un décalage fin si si (compteur<0) alors //on a atteint la premiére valeur du tableau marqueur=faux //il n'y a plus de décalages possibles fin si tantque marqueur T(compteur+1)<-memoire //affectation de la valeur à insérer dans la bonne case fin pour fin Algo. Tri/Recherche Page 8 CER SCHMITT Mathieu Algorithme de tri Shell Ce tri, proposé en 1959 par Donald L. Shell, constitue une variante optimisée du tri par insertion. Le tri par insertion provoquait le décalage de tous les éléments plus grands que l'élément à insérer. Dans le tri Shell, les éléments ne sont pas décalés d'un élément à la fois, mais de plusieurs éléments, dont la différence d'indice est appelée "pas". Ainsi, à chaque étape, le tri est dégrossit puis le pas est réduit. Chaque réduction de pas provoque un affinage du tri. Lorsque le pas atteint la valeur 1, cela revient à effectuer le tri par insertion. Cependant, cette fois, le tri par insertion est appliqué à un tableau possédant un certain ordre (provoqué par les étapes de préparations où le pas est supérieur à un). En effet, les différentes étapes où le pas est supérieur à un provoque le regroupement des différentes valeurs par groupes de la même taille que le pas. Ainsi par exemple, après une étape où le pas est de quatre, les quatre premières valeurs du tableau sont les quatre plus petites, les quatre suivantes sont plus grandes… En résumé, le tri Shell permet d'organiser plus rapidement le tableau à trier. Le choix du pas ne doit pas s'effectuer n'importe comment. En effet, les valeurs des différents pas successifs ne doivent pas, pour des raisons de plus grande efficacité, être multiples des autres et il faut absolument réaliser l'étape ou le pas est égal à un. La formule la plus couramment utilisée pour calculer la valeur des pas successifs est la suivante U(n+1)=(3Un+1) avec U0=0. Soit n le nombre d'éléments du tableau et p le pas, le pas doit être tel que p<n. Certains algorithmes imposent la taille des pas successifs, qui sont, par exemple, écrits en dur au sein du programme. L'inconvénient est que le nombre de valeurs à trier peut être bien supérieur au plus grand pas prévu par la personne ayant implémenté l'algorithme. La version qui est proposée ici préfère calculer, à l'aide de la formule donnée ci-dessus, le plus grand pas p tel que p<n. Pour trouver les autres valeurs successives de p, il suffit, à chaque étape, de diviser p par 3 (division entière). Exemple : Evolution du tableau au fil du tri shell. Le pas, représenté en rouge est également indiqué ainsi que la valeur en mémoire, sur laquelle porte la comparaison. En bleu, les valeurs sur lesquels portent les comparaisons à chaque étape. Algo. Tri/Recherche Page 9 CER SCHMITT Mathieu A ce stade, le tri fusion revient à effectuer le tri par insertion. L'exemple s'arrêtera donc ici. Il faut cependant remarquer que, grâce aux différentes étapes du tri Shell, le tableau est un peu mieux organisé : La moyenne des valeurs de la première moitié du tableau a diminué. Ce résultat est d'autant plus remarquable que le tableau à trier est grand. Algo. Tri/Recherche Page 10 CER SCHMITT Mathieu Pseudo-code : Algorithme de tri Shell tri_shell(tableau T) debut entier longueur, n, i, j, valeur; longueur<-taille(T) n<-0; tantque n<longueur faire n<-(3*n+1) //calcul du plus grand décalage possible fin tantque tantque n != 0 faire //tant que le décalage possible est non nul n<-(n/3) pour i=n à longueur-1 faire valeur<-T(i) //valeur à décaler (éventuellement) j<-i tantque (j>n-1) et (T(j-n)>valeur) T(j)<-T(j-n) //décalage des valeurs avec un pas de n j<-j-n fin tantque T(j)<-valeur fin pour fin tantque fin Algo. Tri/Recherche Page 11 CER SCHMITT Mathieu Algorithme de tri fusion ou tri dichotomique Le tri fusion est construit suivant la stratégie "diviser pour régner", en anglais "divide and conquer". Le principe de base de la stratégie "diviser pour régner" est que pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires. Une fois chaque petit problème résolu, il n'y a plus qu'à combiner les différentes solutions pour résoudre le problème global. La méthode "diviser pour régner" est tout à fait applicable au problème de tri : plutôt que de trier le tableau complet, il est préférable de trier deux sous tableaux de taille égale, puis de fusionner les résultats. L'algorithme proposé ici est récursif. En effet, les deux sous tableaux seront eux même triés à l'aide de l'algorithme de tri fusion. Un tableau ne comportant qu'un seul élément sera considéré comme trié : c'est la condition sine qua non sans laquelle l'algorithme n'aurais pas de conditions d'arrêt. Exemple : Grandes étapes de l'évolution du tableau au fil de l'algorithme : Algo. Tri/Recherche Page 12 CER SCHMITT Mathieu Pseudo code : fusion(tableau T,entier premier1,entier dernier1,entier dernier2) debut tableau Tbis entier premier2, compteur1, compteur2, i premier2<-dernier1+1 compteur1<-premier1 compteur2<-premier2 taille(T)<-(dernier1-premier1+1) //taille du premier sous tableau //on recopie dans T les éléments du premier sous tableau pour i=premier1 à dernier1 faire Tbis(i-premier1)<-T(i) fin pour //on fusionne ensuite les deux sous tableaux pour i=premier1 à dernier2 faire si compteur1=premier2 alors //tous les éléments du premier sous tableau ont été utilisés arret pour //tous les éléments sont donc classés sinon si compteur2=(dernier2+1) alors //tous les éléments du second sous tableau ont été utilisés T(i)=Tbis(compteur1-premier1) //on recopie à la fin du tableau les éléments du premier sous tableau compteur1<-compteur1+1 sinon si Tbis(compteur1-premier1)<T(compteur2) alors //l'élément du premier sous tableau est le plus petit T(i)<-Tbis(compteur1-premier1) //on ajoute un élémnt du premier sous tableau compteur1<-compteur1+1 //on progresse dans le premier sous tableau sinon //c'est l'élément du second sous tableau qui est le plus petit T(i)<-T(compteur2) //on recopie cette élément à la suite du tableau compteur2<-compteur2+1 //on progresse dans le second tableau fin si fin pour fin Algo. Tri/Recherche Page 13 CER SCHMITT Mathieu tri_fusion_bis(tableau T,entier premier,entier dernier) debut entier milieu; si premier<>dernier alors //si l'indice du premier et du dernier élément à traiter //est différent (condition d'arret de l'algorithme) milieu<-(premier+dernier)/2 tri_fusion_bis(T,premier,milieu) //tri de la premiére moitiée du sous tableau tri_fusion_bis(T,milieu+1,dernier) //tri de la seconde moitiée du sous tableau fusion(T,premier,milieu,dernier) //fusion des deux sous moitiées fin si fin tri_fusion(tableau T) debut entier longueur longueur<-taille(T) si longueur>0 alors tri_fusion_bis(T,0,longueur-1) fin si fin Algo. Tri/Recherche Page 14 CER SCHMITT Mathieu Etudier les algorithmes de recherche et leurs contextes Recherche linéaire Fonction : Recherche_Linéaire( tableau T[], entier v) : entier debut //Sortie : 1ère position de v dans T ou (-1) si v n’est pas dans T Entier Pos <-- 0 Tant que pos < taille T et T(pos) != v faire Pos <-- pos + 1 fin tant que si pos >= taille T alors retourner -1 sinon retourner pos fin si fin Recherche séquentielle Recherche(element X,liste L) : booleen Debut entier p //position p<-debut(L) // premier élément si p<>INCONNUE alors retourner FAUX // cas liste vide sinon // liste non vide tant que p<>fin(L) et non elements_egaux(acces(p,L),X) faire p <- suivante(L,p) fintantque retourner elements_egaux(acces(p,L),X) finsi fin Algo. Tri/Recherche Page 15 CER SCHMITT Mathieu Recherche dichotomique (ensemble trié seulement) Algo. Tri/Recherche Page 16