Préparation à l’agrégation 2009/2010 Algèbre et Calcul Formel Quelques algorithmes de tri 1 Structure de données On choisit le type list (> ?list ;) pour représenter les listes à trier. Exercice 1 Écrire une procédure swap qui prend en entrée une liste 𝑙, deux entiers 𝑖 et 𝑗, et renvoie 𝑙 où 𝑙[𝑖] et 𝑙[𝑗] ont été échangés (on suppose que la taille 𝑛 de 𝑙 est telle que 𝑛 ≥ max (𝑖, 𝑗)). Exercice 2 Utiliser RandomTools[Generate] pour générer des listes d’entiers choisis aléatoirement entre 1 et 1 000 de tailles variées. 2 Tris en vrac Pour chacun des algorithmes de tri présentés ci-dessous, on demande de calculer : 1. sa complexité dans le meilleur cas 2. sa complexité dans le pire cas 3. une implémentation de l’algorithme en Maple. 2.1 Tri à bulles On parcourt la liste à trier. Chaque fois que deux éléments consécutifs sont dans le désordre, on les inverse et on continue le parcours de la liste. On répète ce parcours tant que la liste n’est pas triée. Notez qu’à la fin du 𝑖-ème parcours, 𝐿[(𝑛 − 𝑖 + 1)..𝑛] est triée et contient les 𝑖 plus grands éléments de la liste. 2.2 Tri par insertion C’est le tri du joueur de carte : à chaque élément qui n’est pas à sa place dans la liste, on parcours la liste qui le précède dont on décale les éléments d’une case vers la droite chacun jusqu’à en trouver un qui est plus petit que l’élément que l’on traite. On insère alors celui-ci à l’emplacement laissé libre dans le tableau. 2.3 Tri fusion Cet algorithme utilise le paradigme « diviser pour régner » : pour trier une liste 𝐿 de taille 𝑛, on trie d’abord 𝐿[1..𝑛/2 − 1], 𝐿[𝑛/2..𝑛], puis on fusionne les deux listes triées. Pour faciliter l’implémentation de cette dernière procédure, on pourra rajouter une valeur +∞, dite « sentinelle » à la fin de chaque liste. On peut montrer que la complexité asymptotique de cet algorithme est optimale. Pour cela, on considère la structure d’arbre de décision, qui va nous permettre d’estimer le nombre de comparaisons qu’un algorithme de tri doit effectuer pour trier une liste, et ainsi fournir une borne inférieure pour celui-ci. C. Picaronny & J. Villard 1 E.N.S. de Cachan Préparation à l’agrégation 2009/2010 Algèbre et Calcul Formel Définition 1 Un arbre de décision est un arbre binaire complet dont chaque nœud est étiqueté par une comparaison 𝑎𝑖 : 𝑎𝑗 entre deux éléments de la liste (on suppose la liste composée d’éléments tous distincts), et dont les feuilles correspondent aux permutations de la liste de départ. Un algorithme de tri devant être capable de produire toutes les permutations de son entrée, le nombre de feuilles d’un tel arbre doit être au moins 𝑛!. Le temps d’exécution dans le cas le plus défavorable correspond à la hauteur de l’arbre, c’est-à-dire au plus long chemin de la racine à une feuille. On en déduit le théorème suivant : Théorème 1 Un algorithme de tri par comparaison nécessite au moins 𝑂(𝑛 lg 𝑛) comparaisons dans le pire cas. 2.4 Tri rapide Pour le tri rapide, on choisit un élément dans la liste qui va servir de pivot : on le place alors à sa place définitive en mettant tous les éléments de la liste qui lui sont inférieurs avant lui. On rappelle ensuite la procédure récursivement sur les deux souslistes obtenues. C’est le tri le plus utilisé en pratique ; pourquoi ? 3 Tri par tas Le tri par tas est un des algorithmes de tri les plus efficaces asymptotiquement, puisqu’il est agit à la fois en place et en temps optimal. Pour cela, il faut avoir recours à la structure de tas. Définition 2 Un tas est un arbre binaire presque complet, c’est-à-dire dont tous les niveaux sont remplis, à l’exception éventuelle du dernier qui se rempli de gauche à droite. Un tas-max est un tas dont chaque nœud a une valeur inférieure à celle de son parent. Il est facile de représenter un tas par un tableau en rangeant les éléments par profondeurs successives, car le calcul des positions du parent et des deux fils d’un nœud à la position 𝑖 dans le tableau correspondent respectivement à ⌊𝑖/2⌋, 2𝑖 et 2𝑖 + 1. Exercice 3 On suppose donné un tas max sous forme d’une liste 𝐿. Écrire une procédure Entasser(L,a) qui insère 𝑎 dans 𝐿 en préservant la structure de tas max. Montrer que la complexité de votre procédure est en 𝑂(lg ∣𝐿∣). Exercice 4 Donner une procédure pour transformer en place une liste en tas max. Exercice 5 En déduire l’algorithme du tri par tas et montrer que sa complexité est en 𝑂(𝑛 lg 𝑛). Bonus Refaire le TD en utilisant le type Array à la place du type list. On pourra écrire des fonctions size, elements, . . . pour s’abstraire de nops, op, . . . C. Picaronny & J. Villard 2 E.N.S. de Cachan