INF1101 Algorithmes et structures de données Cours 6 Algorithmes de tri INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Plan du cours 6 I. Notions de base II. Les tris simples III. Mergesort Quicksort INF1101 Algorithmes et structures de données
I – Notions de base: l’utilité des tris Problématique: Un grand nombre de problèmes réels ont recours à la recherche d’éléments dans un vecteur (tableau). Cette recherche devient quasiment impossible lorsqu’elle s’effectue dans un vecteur désordonné, d’où le besoin de trier les vecteurs avant d’y effectuer un traitement. Exemples: Les mots dans un dictionnaire. Fichiers dans un répertoire de PC. Les CD répertoriés dans un magasin de musique. Les sigles des cours de Poly offert pour une session. INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Définitions Tri interne : se dit d'un algorithme qui n'utilise pas de tableau temporaire pour effectuer le tri. Tri externe : se dit d'un algorithme de tri qui nécessite l'utilisation d'un tableau temporaire. INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données II – Les tris simples Tri par sélection Tri en bulle Tri par insertion INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Tri par sélection Idée : Cette technique consiste à parcourir séquentiellement le vecteur à trier. À l'itération i, la plus petite valeur du tableau est interchangée avec la valeur située dans la case d'indice i. INF1101 Algorithmes et structures de données
Exemple d’exécution du tri par sélection min = [4] [0] [3] [1] [2] [4] 15 10 i = 3 1 2 8 7 2 0 1 2 3 4 i INF1101 Algorithmes et structures de données
Programmation du tri par sélection template<class T> void TriSelection( vector<T>& Tableau, int n) { int i, j, min; T Tmp; for ( i=0 ; i<n-1 ; i++ ) { //Identification de l'index du plus petit element min = i; for ( j=i+1 ; j<n ; j++ ) { if ( Tableau[j]<Tableau[min] ) min = j; } //Permutation des elements Tmp = Tableau[i]; Tableau[i] = Tableau[min]; Tableau[min] = Tmp; INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Tri en bulle Idée : Les petits éléments du tableau « remontent » (comme des bulles) vers le début du tableau pour atteindre leur position finale. Les plus « légers » remontent le plus rapidement. Une fois tous les éléments remontés, le tableau est trié. INF1101 Algorithmes et structures de données
Exemple d’exécution du tri en bulle : comparaison de deux éléments 15 10 8 7 2 0 1 2 3 4 i Position de i INF1101 Algorithmes et structures de données
Programmation du tri en bulle template<class T> void TriBulle(vector<T>& Tableau, int n) { int i,j; T Tmp; for ( i=0; i<n-1; i++) for ( j=n-1; j>i; j--) if ( Tableau[j-1]> Tableau[j]) Tmp = Tableau[j-1]; Tableau[j-1] = Tableau[j]; Tableau[j] = Tmp; } INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Tri par insertion Idée : Cette stratégie est semblable à la méthode qu'utilise naturellement un joueur de cartes pour organiser sa main. À chaque étape, une partie du tableau est déjà ordonnée et une nouvelle valeur est insérée à l'endroit approprié. INF1101 Algorithmes et structures de données
Exemple d’exécution par insertion 15 10 8 7 2 0 1 2 3 4 i INF1101 Algorithmes et structures de données
Programmation du tri par insertion template < class T> void TriInsertion(vector<T>& Tableau, int n) { int i,j; T Tmp; for ( i=1;i<n; i++ ) //Placer l'element courant dans la variable tampon Tmp = Tableau[i]; j=i; //Tant que la position d'insertion n'est pas atteinte... while ( (--j>=0) && (Tmp<Tableau[j]) ) Tableau[j+1]=Tableau[j]; Tableau[j+1]=Tmp; } INF1101 Algorithmes et structures de données
Analyse des tris simples Meilleur cas: tableau déjà trié Cas moyen: tableau aléatoire Pire cas: tableau trié à l’envers 1 3 5 7 9 10 13 18 21 25 7 10 21 9 1 25 18 3 5 13 25 21 18 13 10 9 7 5 3 1 INF1101 Algorithmes et structures de données
Comparaison des tris simples Pire cas Cas moyen Meilleur cas Tri par sélection Tri en bulle Tri par insertion INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données III – Le mergesort Problématique : Le tri est effectué en utilisant la technique de diviser-et-conquérir, en divisant le problème en deux sous-problèmes de complexité résolus récursivement, offrant une complexité globale de L'algorithme de tri Mergesort : Si le nombre d’éléments à trier == (0 ou 1), retourner. Trier récursivement la première et deuxième moitié séparément. Regrouper les deux parties triées dans un nouveau groupe trié. INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données MergeSort 1 1 13 13 24 24 26 26 2 2 15 15 27 27 38 38 Actr Bctr Cctr INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données La fonction Mergesort // Routine interne : Tableau: le vecteur d’éléments // tmpTab: vecteur temporaire pour les résultats // left, right: indices gauche et droit des tableaux template <class T> void mergeSort(vector<T>& Tableau, vector<T>& tmpTab, int left, int right) { if (left < right) int center = (left+right)/2; mergeSort(Tableau, tmpTab, left, center) mergeSort(Tableau, tmpTab, center+1, right); merge(Tableau, tmpTab, left, center+1, right); } template <class T> // Fonction principale void mergeSort(vector<T>& Tableau) vector<T> tmpTab(Tableau.size()); mergeSort(Tableau,tmpTab,0,Tableau.size()-1); INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données La fonction Merge // Routine interne : Tableau: le vecteur d’éléments // tmpTab: vecteur pour les résultats du merge // leftPos: indice gauche du tableau // rightPos: indice du début de la 2ieme demi // rightEnd: indice droit du tableau template <class T> void merge(vector<T>& Tableau, vector<T>& tmpTab, int leftPos, int rightPos, int rightEnd) { int leftEnd = rightPos-1; int tmpPos = leftPos; int numElements = rightEnd – leftPos +1; //Boucle principale while( leftPos<=leftEnd && rightPos<=rightEnd) if(Tableau[leftPos]<Tableau[rightPos]) tmpTab[tmpPos++]=Tableau[leftPos++]; else tmpTab[tmpPos++]=Tableau[rightPos++]; . . . (suite) INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données La fonction Merge . . . while(leftPos<=leftEnd) // Copie le reste de la 1ere demie tmpTab[tmpPos++]=Tableau[leftPos++]; while(rightPos<=rightEnd) // Copie le reste de la 2ieme demie tmpTab[tmpPos++]=Tableau[rightPos++]; // Copie tmpTableau dans Tableau for( int i=0; i<numElements ; i++, rightEnd--) Tableau[rightEnd]=tmpTab[rightEnd]; } INF1101 Algorithmes et structures de données
IV - Le tri rapide (Quicksort) Problématique : Le tri est une tâche importante en programmation. Il est donc essentiel que celui-ci soit effectué avec efficacité et rapidité. L'algorithme de tri Quicksort tente d'atteindre cet objectif par l'utilisation du concept de récursivité. INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données Le tri rapide (suite) Idée générale : Dans cet algorithme, l'exécution du tri est simplement déléguée à une série d'appels récursifs. Une fonction de partitionnement est d'abord appelée. Cette fonction choisit arbitrairement un pivot qui est utilisé pour subdiviser le tableau en deux parties: une partie de gauche où tous les éléments ont une valeur plus petite ou égale au pivot; une partie de droite où tous les éléments ont une valeur plus grande ou égale au pivot. Par la suite, les deux parties ainsi obtenues sont triées par deux appels récursifs à la fonction de tri rapide. En plus de la fonction principale de tri rapide, une autre fonction est donc requise: celle qui procède à la partition du tableau. INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données La fonction Quicksort template <class T> void QuickSort(vector<T>& tableau, int inf, int sup) { int milieu; if (sup>inf) // s'il y a au moins 2 éléments milieu = Partition(tableau, inf, sup); // trier la partie de gauche QuickSort(tableau, inf, milieu); // trier la partie de droite QuickSort(tableau, milieu+1, sup); } INF1101 Algorithmes et structures de données
Exemple d’exécution de Partition Premier appel Quicksort(a,0,4) Pivot = Tab[2] = 5 j i 11 9 7 5 2 0 1 2 3 4 i INF1101 Algorithmes et structures de données
INF1101 Algorithmes et structures de données La fonction Partition template <class T> int Partition(vector<T>& tableau, int inf, int sup) { T pivot, tempo; int i,j; pivot = tableau[(sup+inf)/2]; i = inf-1; j = sup+1; // Suite a la page suivante INF1101 Algorithmes et structures de données
La fonction Partition (suite) while ( i<j ) // tant que les index ne croisent pas { // conserver les éléments plus petits ou égaux //au pivot à sa gauche do { i++; } while (tableau[i]<pivot); // conserver les éléments plus grands ou //égaux au pivot à sa droite { j--; } while (tableau[j]>pivot); // Permuter les éléments qui ne sont pas // à leur place if ( i<j) { tempo = tableau[i]; tableau[i]= tableau[j]; tableau[j]= tempo; } return j; } INF1101 Algorithmes et structures de données
Complexité du Quicksort Cas moyen et meilleur cas Complexité du Quicksort dans le cas moyen et dans le meilleur cas . Pire cas Complexité du Quicksort dans le pire cas: INF1101 Algorithmes et structures de données