Lycée Roland Garros - BCPST 1 TP INFO n o Informatique 6. Algorithmes de tri On appelle algorithme de tri tout algorithme qui opère sur une liste de nombres pour renvoyer la même liste triée, c'est à dire contenant les mêmes valeurs dans l'ordre croissant. Dans ce TP nous allons programmer deux algorithmes de tri classiques : le tri par insertion et le tri à bulles. Dans un deuxième temps nous comparerons, à l'aide d'un chronomètre, leurs performances à celles de la fonction de tri pré-existante en Python (la fonction sorted). Nous constaterons que nos algorithmes sont bien moins performants. Ils possèdent cependant un intérêt pédagogique et sont bien plus simples que sorted. C'est un excellent exercice de programmation ! Avant de se lancer : pour tester vos algorithmes, vous pouvez créer facilement une liste de n nombres au hasard entre a et b. Faites pour cela : I import numpy as np . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (une fois pour toutes) I L=list(np.random.randint(a,b,n)) I print(L) 1 Tri par insertion Cette méthode consiste à traiter un par un les éléments de la liste, en la parcourant de la gauche vers la droite, comme on fait pour trier manuellement un jeu de cartes. Principe du tri par insertion : pour chaque élément, en commençant par le deuxième jusqu'au dernier, on le déplace vers la gauche (en inversant sa place avec son voisin de gauche) jusqu'à ce qu'il ait trouvé sa place parmi les éléments déjà triés. Voici un exemple qui illustre les insertions successives : la case grisée représente l'élément que l'on s'apprête à insérer à sa place. Complétez le résultat des étapes manquantes ! 1 Exercice 1 Tri par insertion Ecrire la fonction triinsertion(L) qui réalise cet algorithme, dans un script Python. 2 Tri à bulles Dans cet algorithme on eectue un certain nombre de parcours de la liste. Au cours de chaque parcours, on examine chaque paire de valeurs voisines (L[1] et L[2], puis L[2] et L[3],. . . ), et on les échange à chaque fois qu'elles ne sont pas dans l'ordre croissant. A la n d'un parcours, on recommence un nouveau parcours de la même façon, jusqu'à ce que lors de l'un de ces parcours aucune paire ne soit échangée : la liste est alors triée. Voici plus bas un exemple d'UN parcours d'une liste : 2 Exercice 2 Tri à bulles Ecrire la fonction tribulle qui réalise cet algorithme, dans votre script Python. 3 Calcul de la médiane d'une liste de nombres La médiane d'une liste est la valeur qui se trouve précisément au milieu de la liste, une fois celle-ci triée (dans le cas où la liste est de longueur paire, la médiane est la moyenne entre les deux valeurs du milieu de la liste). Par exemple, la médiane de [1,4,3,6,99,4,3] est 4 ; la médiane de [6,8,13,-5,0,0,2,10,11,55] est 7. La médiane est un indicateur fréquemment utilisé en statistique. Exercice 3 Médiane Ecrire la fonction mediane qui prend une liste en argument et renvoie sa médiane. On fera bien sûr appel à l'une des fonctions de tri déjà créées. 4 Complexité des algorithmes de tri Comme on l'a dit, les deux algorithmes de tri que l'on vient d'étudier ne sont pas performants (c'est-à-dire pas rapides), donc peu utilisés en pratique. Pour décrire la performance d'un algorithme, il faut examiner de quelle façon son temps d'exécution dépend de la taille des données. Pour trier une liste de taille N , ce temps est-il proportionnel à N , à N 2 , ou autre ? Ceci donne une idée, en ordre de grandeur, du temps mis par un algorithme à trier une énorme liste : est-ce de l'ordre de la seconde ? de la minute ? du siècle ? C'est la notion de complexité d'un algorithme. Remarque. En fait pour mesurer la complexité d'un algorithme on ne compte pas en unités de temps mais en nombre d'opérations eectuées. Le temps d'exécution est en eet un mauvais indicateur car il dépend de la performance de la machine qui exécute l'algorithme. Trier une liste, en pratique : Python a une fonction pré-existante pour trier une liste. Il sura en eet de taper sorted(L) pour trier la liste L. Cette fonction utilise un algorithme plus complexe : l'algorithme quicksort. Celui-ci sera étudié en 2ème année. 3 Exercice 4 Comparaison des performances : la théorie 1. Pour les algorithmes de tri à bulle et de tri à insertion, quelles est la pire liste à trier parmi les listes de taille N (celle qui demande le plus d'opérations) ? 2. Combien d'opérations sont nécessaires pour la trier à l'aide de chacun de ces algorithmes ? On donnera la réponse en fonction de la taille N de la liste. 3. En comparaison, l'algorithme quicksort a une complexité en N log N . Com- parer avec celle des deux autres algorithmes pour N = 1000, N = 106 , N = 109 . Exercice 5 Comparaison des performances : la pratique 1. Importer la bibliothèque time avec l'instruction suivante en début de script : import time 2. Faites Ctrl+E si pas déjà fait. Tester plusieurs fois, dans le shell, la commande time.clock() Que fait cette commande ? 3. Application : ajouter un chronomètre à vos fonctions de tri. En clair, vos fonctions devront donc maintenant mesurer et acher leur temps d'exécution (le temps écoulé entre l'instant où vous appuyez sur Entrée et l'instant où la fonction se termine). 4. Comparer alors la performance • du tri à bulle, • du tri par insertion, • de la commande sorted. On pourra pour cela travailler avec une liste aléatoire de longueur N et faire varier N . On peut aussi faire le même travail avec des listes rangées dans l'ordre décroissant. 4