SDA SDA Tris Tris Introduction à la Programmation Objet : Objectifs du cours d’aujourd’hui Continuer l’approfondissement de la programmation de base en présentant d’autres thèmes de l’informatique : Structures de données abstraites Algorithmes de tri ◮ Laboratoire d’Intelligence Artificielle Faculté I&C ◮ c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam introduction aux structures de données abstraites (sda) : ◮ listes chaînées ◮ piles introduction aux algorithmes de tris IPO – Cours 12 :– Récursivité | Complexité– – 1 / 54 SDA Listes Pourquoi modéliser les données ? Piles IPO – Cours 12 :– Récursivité | Complexité– – 2 / 54 SDA Listes Une “structure de données abstraite” ?!? Piles Tris Tris L’élaboration d’un algorithme est grandement facilité par l’utilisation de structures de données abstraites, de plus haut niveau, et de fonctions de manipulations associées. Une structure de données doit modéliser au mieux les informations à traiter pour en faciliter le traitement par l’algorithme considéré. Exemples généraux : tableau (au sens général du terme) contenu : divers éléments de types à préciser interactions : demander la taille du tableau, accéder (lecture/écriture) à chaque élément individuellement, ... Choisir les bons modèles de données est aussi important que le choix de bons algorithmes Algorithme et structure de données abstraite sont intimement liés : Exemple informatique élémentaire : Programme = algorithme + données Vous connaissez déjà des structures de données abstraites, très simples : les types élémentaires. c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 3 / 54 Une structure de données abstraite (S.D.A.) est un ensemble organisé d’informations (ou données) reliées logiquement et pouvant être manipulées non seulement individuellement mais aussi comme un tout. Par exemple, un int interactions : affectation, lecture de la valeur, +, -, *, / IPO – Cours 12 :– Récursivité | Complexité– – 4 / 54 SDA Listes Piles Tris Spécifications des structures de données abstraites SDA Listes Tris Une S.D.A. est caractérisée par : ◮ son contenu ◮ Une structure de données abstraite définit une abstraction des données et cache les détails de leur implémentation. les interactions possibles (manipulation, accès, ...) Par exemple, vous ne pensez pas un int comme une suite de 32 bits, mais bien comme un “entier” (dans un certain intervalle) avec ses opérations propres : +, -, *, / Du point de vue informatique, une structure de données abstraite peut être spécifiée à deux niveaux : ◮ niveau fonctionnel / logique : spécification formelle des données et des algorithmes de manipulation associés ◮ niveau physique (conception) : comment est implémentée la structure de données abstraite dans la mémoire de la machine Spécifications des S.D.A. [2] Piles abstraction : identifier précisément les caractéristiques de l’entité (par rapport à ses applications), et en décrire les propriétés. ☞ déterminant pour l’efficacité des programmes utilisant ces données. c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 6 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 5 / 54 SDA Listes Spécifications des S.D.A. [3] Piles SDA Listes Divers exemples de S.D.A. Piles Tris Tris Une structure de données abstraite modélise donc l’ensemble des services désirés plutôt que l’organisation intime des données (détails d’implémentation) On identifie usuellement quatre types de “services” : Il existe de nombreuses structures de données abstraites en informatique. Dans ce cours, nous n’allons voir que deux parmi les plus fondamentales : 1. les modificateurs, qui modifient la S.D.A. 2. les sélecteurs, qui permettent “d’interroger” la S.D.A. ◮ ◮ 3. les itérateurs, qui permettent de parcourir la structure 4. les constructeurs Exemple : tableau modifieur : affectation d’un élément (t[i]=a) sélecteur : lecture d’un élément (t[i]) sélecteur : le tableau est-il vide ? (t.length == 0) itérateur : index d’un élément ([i] ci-dessus) constructeur :(new) Autres : ◮ files d’attente (avec ou sans priorité) ◮ ◮ ◮ ◮ c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 7 / 54 les listes et les piles multi-listes arbres (plein de sorte...) graphes tables de hachage IPO – Cours 12 :– Récursivité | Complexité– – 8 / 54 SDA Listes Listes SDA Listes Piles Listes Piles Tris Tris Exemple concret : visionneuse stéréo (essayez d’accéder Spécification logique : Ensemble d’éléments successifs (pas d’accès direct), ordonnés ou non à la 3e image directement, sans passer par la 2e !) Interactions : ◮ Accès au premier élément (sélecteur) ◮ ◮ ◮ ◮ ◮ Accès à l’élément suivant d’un élément (sélecteur) Modifier l’élément courant (modificateur) Exemple informatique : Insérer/supprimer un élément après(/avant) l’élément courant (modificateur) ( a ( b ( c (d)))) Tester si la liste est vide (sélecteur) Parcourir la liste (itérateur) a b c d 0 Une liste peut être vue comme une structure récursive : c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 9 / 54 SDA Listes Réalisations d’une liste Tris J. Sam liste = vide Listes Pourquoi des listes dynamiques ? Piles ◮ ◮ c EPFL 2002–2012 OU IPO – Cours 12 :– Récursivité | Complexité– – 10 / 54 SDA Piles liste = élément + liste Réalisation statique : tableau Réalisation dynamique (liste chaînée) : class Liste { Noeud tete; // le debut de la liste Noeud courant; // l’element sur lequel //on est positionn’e ... void inserer(Type donnee) { ... } } class Noeud { Type donnee; Noeud suivant; Noeud(Type donnee) { this.donnee = donnee; suivant = null;} } IPO – Cours 12 :– Récursivité | Complexité– – 11 / 54 Tris Les tableaux sont un type de donnée très utile en programmation mais présentent deux limitations : 1. Les données sont contigües (les unes derrière les autres) et donc l’insertion d’un nouvel élément au milieu du tableau demande la recopie (le décalage) de tous les éléments suivants. =⇒ insertion en O(n) 2. Pour les tableaux statiques, augmenter la taille (par exemple si elle n’est pas connue a priori) nécessite la création d’un nouveau tableau =⇒ O(n) c EPFL 2002–2012 J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 12 / 54 SDA Listes Piles Tris Complexité des opérations élémentaires sur les listes SDA Listes Exemples d’insertion d’un élément Piles Tris ◮ Insérer un élément : O(1) Supprimer un élément : O(1) Après un élément donné (l’élément courant ici) : void insere(Type donnee) { Noeud e = new Noeud(donnee); e.suivant = (this.courant).suivant; courant.suivant = e; } Calculer la longueur : O(n) (voire O(1) si le stockage de cette valeur est effectué, par exemple en particulier si “longueur” a été spécifiée dans les “services” de la SDA “liste”) Vider la liste : O(n) Parcourir la liste : tête O(n) 2 c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam Listes Exemple de calcul de la longueur Piles 1 nouveau noeud donnée IPO – Cours 12 :– Récursivité | Complexité– – 13 / 54 SDA courant IPO – Cours 12 :– Récursivité | Complexité– – 14 / 54 SDA Listes Piles Piles Tris Tris Spécification : Une pile est une structure de données abstraite dynamique contenant des éléments homogènes (de type non précisé) à 1 point d’accès et permettant int taille(Liste liste) { int taille=0; Noeud n=tete; while (!n.suivant == null) { taille++; n = n.suivant; } return taille; } ◮ ◮ ◮ ◮ d’ajouter une valeur à la pile (empiler ou push); de lire la dernière valeur ajoutée ; d’enlever la dernière valeur ajoutée (dépiler ou pop); de tester si la pile est vide. On ne “connait” donc de la pile que son dernier élément. Exemple d’implémentation physique : tableau c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 15 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 16 / 54 SDA Listes Piles : exemples SDA Listes Piles Piles : exemples (2) Piles Tris Tris Exemple d’utilisation (formelle) : Exemples concrets : ◮ ◮ ◮ empiler x x empiler a a x dépiler x empiler b b x empiler y y b x dépiler b x une pile d’assiettes poupées russes une tour dans le jeu des tours de Hanoi c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 17 / 54 SDA Listes Exemple d’utilisation des piles Piles IPO – Cours 12 :– Récursivité | Complexité– – 18 / 54 SDA Listes Tris Tris Le problème des parenthèses : étant donnée une expression avec des parenthèses, est-elle bien ou mal parenthésée ? ((a + b) ∗ c − (d + 4) ∗ (5 + (a + c))) ∗ (c + (d + (e + 5 ∗ g) ∗ f ) ∗ a) (correct) (a + b)( (incorrect) Encore un peu plus complexe : différentes parenthèses Exemple avec [ et ( Exemple Tant que lire caractère c Si c est ( ou [ empiler c Sinon Si c est ) ou ] c ′ ← lire la pile Si c et c ′ correspondent dépiler Sinon ÉCHEC Si pile vide OK Sinon ÉCHEC ([])[()(()[])] ☞ correct ([)] ☞ incorrect Autres exemples d’utilisation des piles (non traités ici) : ◮ ◮ c EPFL 2002–2012 Vérification de parenthésage Piles tours de Hanoi notation postfixée (ou “polonaise inverse”) : 4 2 + 5∗ (☞ 5 ∗ (4 + 2)) J. Sam Entrée : ([)] empile ( ( empile [ [ ( lu = ), top = [ → ne correspond pas =⇒ ERREUR c EPFL 2002–2012 J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 19 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 20 / 54 SDA Listes Deuxième Exemple SDA Listes Piles Code Java Piles Tris Tris Entrée : ([]()) empile ( ( empile [ [ ( lu ] → correspond =⇒ dépile ( empile ( ( ( lu ) → correspond =⇒ dépile ( lu ) → correspond =⇒ dépile pile vide =⇒ OK c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam boolean check(String s) { Pile p; for (int i=0; i < s.length(); i++) { if (s.charAt(i) == ’(’) || (s.charAt(i) == ’[’)) empile(p,s[i]); else if (s.charAt(i) == ’)’) { if (top(p) == ’(’) depile(p); else return false; } else if (s.charAt(i) == ’]’) { if (top(p) == ’[’) depile(p); else return false; } } return est_vide(p); } IPO – Cours 12 :– Récursivité | Complexité– – 21 / 54 SDA Listes S.D.A en Java IPO – Cours 12 :– Récursivité | Complexité– – 22 / 54 SDA Tris Piles Tris Tris Bien sûr, Java a déjà tout prévu pour vous: ◮ Classes collection du paquetage java.util ◮ ◮ Ensembles Listes ◮ ◮ ◮ ◮ ◮ Terminons nos approfondissements en nous intéressant au problème du tri d’une S.D.A. vecteurs piles listes chaînées .. Maps ☞ semestre de printemps c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 23 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 24 / 54 SDA Tris Algorithmes et données : les tris SDA Tris Les tris Par exemple : on cherche à trier un tableau d’entiers de taille fixe. Les méthodes de tris sont très importantes en pratique non seulement en soi, mais aussi parce qu’elles interviennent dans beaucoup d’autres algorithmes. Elles sont par exemple nécessaires pour faire une recherche efficace. Le problème du tri est également un problème intéressant en tant que tel et un bon exemple de problème pour lequel il existe de nombreux algorithmes. entrée 6 1 2 3 6 2 programme de tri Remarques : ◮ un tri ne supprime pas les doublons Spécification du problème : On considère une structure de données abstraite contenant des éléments que l’on peut comparer entre eux : il existe une relation d’ordre totale sur l’ensemble des éléments On dira que la S.D.A est triée si ses éléments sont disposés par ordre croissant pour l’opérateur de comparaison. ◮ quel que soit l’algorithme de tri, une S.D.A. vide ou réduite à un seul élément est déjà triée !... On parle de tri interne (par opposition à tri externe) lorsque l’on peut effectuer le tri en mémoire dans la machine, sans utiliser de support extérieur (fichier). c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 26 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 25 / 54 SDA Tris sortie 1 2 2 3 6 6 Un premier exemple : le tri par insertion SDA Tris Le principe du tri par insertion est extrêmement simple : 1 3 5 2 4 6 un élément mal placé dans le tableau va systématiquement être inséré à sa “bonne place” dans le tableau. Tant que il y a un élément mal placé on cherche sa bonne place on déplace l’élément à sa bonne place −→ 1 2 3 5 4 6 −→ 1 2 3 4 5 6 Tant que il y a un élément mal placé on cherche sa bonne place on déplace l’élément à sa bonne place Par "élément mal placé", on entend ici tout élément du tableau strictement plus petit que son prédécesseur. c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 27 / 54 Exemple de déroulement du tri par insertion IPO – Cours 12 :– Récursivité | Complexité– – 28 / 54 SDA Tris tri par insertion : résolution globale SDA Tris tri par insertion : résolution détaillée Le bloc mal placé Le schéma général de l’algorithme de tri par insertion est donc le suivant : entrée : un tableau tab sortie : indice du 1er élément de tab de prédécesseur strictement plus grand tri insertion entrée : un tableau sortie : le tableau trié Par convention, s’il n’y a pas d’élément mal placé, la sortie sera l’indice du premier élément du tableau (0 en Java). Tant que il y a un élément mal placé on cherche sa bonne place Comme le 1er élément de tab ne peut être mal placé (car sans prédécesseur), le bloc mal placé parcourira donc les éléments de tab à partir du 2e. on déplace l’élément à sa bonne place Le bloc mal placé effectue donc une itération sur les éléments de tab, du deuxième au dernier. ☞ Il faut spécifier plus clairement les blocs ci-dessus. c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 30 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 29 / 54 SDA Tris tri par insertion : résolution détaillée (2) SDA Tris Le bloc bonne place tri par insertion : résolution détaillée (3) Le bloc déplace entrée : un tableau tab et l’indice pos d’un élément mal placé sortie : l’indice newpos de la bonne place de l’élément mal placé dans le tableau. entrée : un tableau tab, un indice d’origine pos et un indice final newpos Il doit déplacer l’élément d’indice pos dans tab à l’indice newpos. On peut effectuer cette opération par décalages successifs (en utilisant un stockage temporaire tmp). La “bonne position” correspond à la plus grande position newpos (<pos) dans le tableau tab telle que tab[newpos-1]≤tab[pos]. tmp Le bloc bonne place doit donc parcourir les positions de tab, entre le premier élément et pos, à la recherche d’une bonne position. tab c EPFL 2002–2012 Le bloc bonne place effectue donc aussi une itération sur les éléments du tableau, du premier élément à celui d’indice pos. J. Sam ... newpos newpos+1 pos c EPFL 2002–2012 J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 31 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 32 / 54 SDA Tris Tri par insertion : codage SDA Tris tri par insertion : codage (3) Codage de la fonction bonne place : Codage de l’algorithme de tri par insertion : int bonnePlace(int pos, int tab[]) { // il est important de declarer i avant : pourquoi int i; for (i = 0; (i < pos) && (tab[i] <= tab[pos]); i++); return i; } void triInsertion(int tab[], int taille) { for (int pos=malPlace(tab,taille); pos > 0; pos = malPlace(tab,taille)) deplace(pos, bonnePlace(pos,tab), tab); } Codage de la fonction déplace : Codage de la fonction mal placé : void deplace(int pos, int newpos, int tab[]) { int tmp = tab[pos]; // stockage temporaire for (int i=pos; i > newpos; i--) { tab[i] = tab[i-1]; } tab[newpos] = tmp; } int malPlace(int tab[], int taille) { for (int i=1; i < taille; i++) if (tab[i-1] > tab[i]) return i; return 0; } c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 33 / 54 SDA Tris Version récursive IPO – Cours 12 :– Récursivité | Complexité– – 34 / 54 SDA Tris Version récursive : exemple On peut aussi concevoir le tri par insertion de façon récursive : 1 tri entrée : tableau de n éléments sortie : tableau trié 1 condition arrêt : moins de 2 éléments tri (instance réduite du problème) entrée : tableau de n − 1 éléments sortie : tableau trié 3 3 5 5 2 6 4 2 6 4 5 6 4 tri 1 2 3 ... insertion insertion du nème élément dans le tableau trié de n − 1 éléments 1 c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 35 / 54 2 3 4 5 6 IPO – Cours 12 :– Récursivité | Complexité– – 36 / 54 SDA Tris Implémentation récursive SDA Tris Schéma des appels récursifs : exemple L’algorithme de tri récursif sera implémenté en Java par la fonction : // trie le tableau tab entre first et last void triRecursif(int tab[], int first, int last) { if (last > first) // moins de 2 elements -> fini { triRecursif(tab, first, last-1); deplace(last, bonnePlace(last, tab), tab); } } triRecursif({3,2,1},0,2) {1,2,3} triRecursif({3,2,1},0,1); deplace(2, 0, {2,3,1}) {2,3,1} triRecursif({3,2,1},0,0); Appel de départ : deplace(1, 0, {3,2,1}) triRecursif(monTab, 0, taille-1); {3,2,1} c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 37 / 54 SDA Tris Schéma des appels récursifs : explications IPO – Cours 12 :– Récursivité | Complexité– – 38 / 54 SDA Tris En rouge, l’élément est trié (ce qui est automatiquement vrai avec une tableau de taille 1). En vert, l’élément est celui que l’on va insérer au bon endroit. L’appel deplace(1,0,{3,2,1}) dit qu’il faut déplacer l’élément de la position 1 (donc le 2) à la position 0 (donc à la place du 3). Cela donne donc un sous-tableau (indices 0 et 1) trié: {2, 3, 1}. L’idée du tri fusion est de : c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 39 / 54 Autre exemple de tri: le tri par fusion ◮ Séparer le tableau initial en deux parties égales, ◮ Trier chaque partie indépendamment de façon récursive, ◮ Fusionner les deux parties triées ainsi obtenues. IPO – Cours 12 :– Récursivité | Complexité– – 40 / 54 SDA Tris Tri par fusion: complexité(1) SDA Tris Tri par fusion: complexité(2) L’algorithme du tri fusion est alors simple : la fonction trifusion(t, i, j) suivante effectue le tri fusion du tableau t entre les indices i et j. La fusion de deux tableaux triés t1 et t2 (de taille respective n1 et n2 ) ne requiert donc qu’un seul parcours, en parallèle, des deux tableaux en entrée. Complexité linéaire: O(max(n1 , n2 )) trifusion(t, i, j) Si (i== j) retourne le tableau t[i]; Sinon milieu=(i + j)/ 2; t1 = trifusion(t, i, milieu); t2 = trifusion(t, milieu + 1,j); retourner fusion(t1 , milieu- i + 1,t2 , j - milieu); fusion(t1 , n1 , t2 , n2 ) créer un nouveau tableau t; i = 0; j = 0; Tant que (i ≤ n1 et j ≤ n2 ) Si (t1 [i] < t2 [j]) ajouter t1 [i] à t; i++; Sinon ajouter t2 [j] à t; j++; Tant que (i ≤ n1 ) ajouter t1 [i] à t; i++; Tant que (j ≤ n2 ) ajouter t2 [j] à t; j++; retourner t; Dans cet algorithme, la fusion de deux tableaux (de complexité O(n)) sera appelée autant de fois que le tableau initial de taille n peut être récursivement coupé en deux, soit log2(n) fois. La complexité de l’algorithme est donc en O(nlog(n)). c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 41 / 54 SDA Tris ...encore un autre tri: le tri rapide (Quicksort) IPO – Cours 12 :– Récursivité | Complexité– – 42 / 54 SDA Tris Quicksort(1) Pour un tableau A de N éléments, la recherche de l’élément pivot fonctionne de la façon suivante : Un autre algorithme de tri, fondé sur le paradigme Diviser pour régner et appelé quicksort a été proposé en 1962, par C. A. R. Hoare, Cet algorithme: ◮ Permet de placer un élément à sa place (le pivot) ◮ ◮ Ramène ainsi le problème au tri des 2 morceaux de tableau entourant cet élément La séparation du tableau ne se fait donc pas en deux parties égales, mais en deux parties qui entourent un élément bien placé. ◮ Initialisation : i = 2, j = N ◮ Rechercher, en augmentant i, le premier élément supérieur à A1 (il marque la limite des nombres inférieurs à A1 ) et, en diminuant j, le premier élément inférieur à A1 (qu’il faudra placer dans le morceau de tableau des nombres inférieurs à A1 ). ◮ Si i < j, échanger Ai et Aj continuer des traitements identiques jusqu’au moment où i ≥ j on termine par l’échange éventuel de Aj et A1 . On relance l’algorithme récursivement pour trier les deux parties du tableau de part et d’autre de l’élément pivot. c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 43 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 44 / 54 SDA Tris Quicksort(2) SDA Tris Quicksort(3) Prenons par exemple le tableau A suivant à trier : 7 8 9 1 0 2 5 On continue à chercher, en nous déplaçant vers la droite, le premier élément supérieur à A1 mais à partir de A3 . Il s’agit de A3 qui vaut 9. De même, cherchons à partir de A7 et en nous déplaçant vers la gauche, le premier élément inférieur à A1 . Il s’agit de A7 qui vaut 5. 6 Recherchons, à partir de A2 , en nous déplaçant vers la droite, le premier élément supérieur à A1 . Il s’agit de A2 qui vaut 8 (en rouge). De même, cherchons à partir de A8 et en nous déplaçant vers la gauche, le premier élément inférieur à A1 . Il s agit de A8 qui vaut 6 (en magenta). 7 8 9 1 0 2 5 6 6 9 1 0 2 5 6 9 1 0 2 5 8 7 6 5 1 0 2 9 8 On les échange: On les échange 7 7 8 c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 45 / 54 SDA Tris Quicksort(3) IPO – Cours 12 :– Récursivité | Complexité– – 46 / 54 SDA Tris 7 6 5 1 0 2 9 8 On continue à chercher, en nous déplaçant vers la droite, le premier élément supérieur à A1 mais à partir de A4 . Il s agit de A7 qui vaut 9 (i vaut donc 7). De même, cherchons à partir de A6 et en nous déplaçant vers la gauche, le premier élément inférieur à A1 . Il s’agit de A6 qui vaut 2 (j vaut donc 6). 7 6 5 1 0 2 9 Quicksort(4) L’élément en position 6 constitue l’élément pivot. 2 6 5 1 0 7 9 8 Il faut alors trier récursivement les morceaux de tableau dont les indices vont de 1 à 5 et de 7 à 8: 8 2 6 5 1 0 7 9 8 Comme i > j, il n y a pas d’échange mais par contre, on échange A1 et Aj . 2 c EPFL 2002–2012 J. Sam 6 5 1 0 7 9 8 Et l’élément en position 6 est à sa place définitive. Il constitue l’élément pivot . IPO – Cours 12 :– Récursivité | Complexité– – 47 / 54 c EPFL 2002–2012 J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 48 / 54 SDA Tris L’algorithme Quicksort(tableau, inf, sup) SDA Tris Si inf ≤ sup i = inf + 1; j = sup; Tant que i < j Tant que (A[i] < A[inf ] et i < sup) i++: Tant que (A[j] > A[inf ] et j > inf ) j- -; Si (i < j) swap(A[ i], A[ j]); Si (A[j] < A[inf ]) swap(A[j], A[inf ]); i++; j- -; Si (j − 1 > inf ) quicksort(tableau, inf, j - 1); Si (j + 1 < sup) quicksort(tableau, j + 1, sup); On peut montrer que la complexité du quicksort: ◮ ◮ c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam Tris Conclusions sur les tris SDA Tris ◮ ◮ ◮ ◮ ◮ ◮ Est en moyenne en O(nlog(n)) . En pratique, la complexité moyenne du quicksort est même meilleure que la complexité du tri-fusion (car le facteur multiplicatif de nlog(n) est plus petit). Conclusions sur les tris : comparaison COMPLEXITÉ TEMPORELLE moyenne pire cas bulles O(n2 ) O(n2 ) 2 par sélection O(n ) O(n2 ) 2 insertion O(n ) O(n2 ) de Shell – O(n1.5 ) quick sort O(n log n) O(n2 ) par tas O(n log n) O(n log n) fusion O(n log n) O(n log n) optimum théorique O(n log n) O(n log n) Ce n’était qu’une brève introduction, du fait de l’importance des tris. Il existe beaucoup d’autres algorithmes de tris : ◮ Est au pire en O(n2 ) IPO – Cours 12 :– Récursivité | Complexité– – 50 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 49 / 54 SDA Complexité de Quicksort par sélection bulles tri shaker tri de Shell tri tournois tri par tas ... Mais en pratique : à partir de quelle taille les méthodes simples deviennent-elle vraiement plus mauvaises que les méthodes sophistiquées (quick sort ou tri par tas) ? c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 51 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 52 / 54 SDA Tris Conclusions sur les tris : comparaison (2) SDA Tris Cela dépend de nombreux facteurs, mais en général on peut dire que pour moins d’une centaine d’éléments les tris sophisitiqués n’en valent pas la peine. Ce que j’ai appris aujourd’hui ◮ Expérimentalement le quick sort est 2 a 3 fois plus rapide que le tris par tas ◮ Dans le cas de liste presque triées, les tris par insertion sont efficaces. ◮ les bases de la formalisation des données : les structures de données abstraites les deux structures de données abstraites les plus utilisées en informatique (en plus des tableaux et des types élémentaires) : les listes chaînées et les piles introduction aux algorithmes de tri Le tri bulles, très simple à écrire, est le moins bon des tris : à proscrire (sauf à des fins pédagogiques). c EPFL 2002–2012 c EPFL 2002–2012 J. Sam J. Sam IPO – Cours 12 :– Récursivité | Complexité– – 53 / 54 IPO – Cours 12 :– Récursivité | Complexité– – 54 / 54