You are on page 1of 12

Algorithmes de tri (1/2)

Problmatique : tant donn une structure linaire (tableau, liste, etc) contenant des valeurs d'un type ordonn, il faut trier les lments en ordre croissant (ou dcroissant). Il existe des dizaines d'algorithmes rpondant ce problme, utilisant quelques principes de base auxquels on ajoute des variantes On peut distinguer :
les tris internes qui trient les lments dans la structure qui les contient (tableau, liste, ...) ou au pire utilise une structure annexe de mme type les tris externes utiliss lorsque la quantit d'lments trier est telle qu'ils ne tiennent pas en mmoire vive et qu'il faut stocker des lments dans des fichiers ou des tables de bases de donnes

Algorithmes de tri (2/2)


Proprits des algorithmes de tri :
complexit en temps et en espace stabilit : l'algorithme ne modifie pas l'ordre initial des lments gaux par comparaison tri sur place ou pas : l'algorithme n'utilise pas de mmoire supplmentaire (hormis ventuellement quelques indices de boucle ou boolens), les lments sont tris directement dans la structure de donnes

La plupart des algorithmes de tri utilisent la comparaison d'lments 2 2


on montre que le nombre minimum de comparaisons effectuer est nlog(n) si n est la taille de la structure. Les algorithmes en O(n2) sont donc peu efficaces, ceux au pire en O(nlog(n)) sont optimaux il existe des tris linaires, mais ils n'utilisent pas la comparaison et sont limits des cas trs particuliers (tris de nombres dont on connait des proprits statistiques)

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri bulle (1/7)


Principe du tri bulle (bubble sort) : l'lment le plus grand remonte au bout du tableau, comme une bulle de champagne, puis on recommence pour que le deuxime plus grand remonte, etc. L'criture de l'algorithme s'inspire de l'algorithme squentiel qui vrifie si un tableau est tri. Algorithme : i dsigne la dernire case traiter
fonction sans retour triBulle(entier[] tab){ entier i,j,temp; dbut pour (i allant de tab.longueur-2 1 pas -1) faire pour (j allant de 0 i pas 1) faire si (tab[j] > tab[j+1]) alors temp <- tab[j]; tab[j] <- tab[j+1]; tab[j+1] <- temp; finsi finpour finpour fin
3

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri bulle (2/7)


Exemple : trier en ordre croissant le tableau suivant
701 | 17 | 2 | 268 | 415 | 45 | 45 | 102
premier tour de la premire boucle (sur i) j=0 j=1 j=2 j=3 j=4 j=5 j=6

17 | 701 | 2 | 268 | 415 | 45 | 45 | 102 17 | 2 | 701 | 268 | 415 | 45 | 45 | 102 17 | 2 | 268 | 701 | 415 | 45 | 45 | 102 17 | 2 | 268 | 415 | 701 | 45 | 45 | 102 17 | 2 | 268 | 415 | 45 | 701 | 45 | 102 17 | 2 | 268 | 415 | 45 | 45 | 701 | 102 17 | 2 | 268 | 415 | 45 | 45 | 102 | 701

Tri bulle (3/7)


deuxime tour de la premire boucle (sur i)

2 | 17 | 268 | 45 | 45 | 102 | 415 | 701

troisime tour de la premire boucle (sur i)

2 | 17 | 45 | 45 | 102 | 268 | 415 | 701


quatrime tour de la premire boucle (sur i)

2 | 17 | 45 | 45 | 102 | 268 | 415 | 701


Problme : l'algorithme va faire 3 tours supplmentaires de la boucle sur i, inutilement

Tri bulle (4/7)


Complexit du tri bulle en fonction de la taille n du tableau :
la remonte du plus grand lment utilise (n-1) comparaisons, la remonte du deuxime plus grand utilise (n-2), etc. La complexit sera donc toujours proportionnelle (n-1)+(n-2)+...+1 = n*(n-1)/2 soit O(n2).

Le tri bulle est en place et l'algorithme donn ici est stable (il serait instable si on utilisait au lieu de >) Une amlioration possible du tri bulle consiste utiliser une variable boolenne drapeau qui permet de stopper le tri si plus aucune permutation n'a lieu

5 6

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri bulle (5/7)


fonction sans retour triBulle(entier[] tab){ entier i,j,temp; booleen b; dbut b <- faux; i <- tab.longueur-2; tantque ((non b) et (i > 0)) faire b <- vrai; pour (j allant de 0 i pas 1) faire si (tab[j] > tab[j+1]) alors temp <- tab[j]; tab[j] <- tab[j+1]; tab[j+1] <- temp; b <- faux; finsi finpour i <- i-1; fintantque fin

Remarques : la complexit au pire et en moyenne reste en O(n2) mais est linaire au mieux cette amlioration n'est efficace que si le tableau est dj un peu tri et qu'il devient tri assez vite
7

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Une autre amlioration possible du tri bulle est le tri Boustrophedon (du nom des critures qui changent de sens chaque ligne) :
on parcourt le tableau de gauche droite, en faisant remonter l'lment le plus grand on redescend le tableau de droite gauche, en faisant descendre le plus petit on recommence en ignorant les 2 lments dj tris la complexit au pire et en moyenne est toujours en O(n2) mais est rduite du fait qu'on peut exploiter les bonnes positions des petits lments comme des plus grands

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri bulle (6/7)

Tri bulle (7/7)


Tri par la mthode du tri bulle de tableaux d'entiers gnrs alatoirement

Tri slection (1/3)


Principe du tri slection (ou tri par extraction) : on parcourt le tableau pour trouver le plus grand lment, et une fois arriv au bout du tableau on y place cet lment par permutation. Puis on recommence sur le reste du tableau. Algorithme : i dsigne la dernire case traiter
fonction sans retour triSelection(entier[] tab){ entier i,j,temp,pg; debut i <- tab.longueur-1; tanque (i > 0) faire pg <- 0; pour (j allant de 0 i pas 1) faire si (tab[j] > tab[pg]) alors pg <- j; finsi finpour temp <- tab[pg]; tab[pg] <- tab[i]; tab[i] <- temp; i <- i-1; fintantque fin

01

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri slection (2/3)


Complexit du tri slection : chaque tour de la boucle tantque, on fait i tours de boucle pour. La complexit sera donc dans tous les cas proportionnelle (n-1)+(n-2)+...+1 =n*(n-1)/2 et donc en O(n2).
Remarque : le tri slection utilise une variable de plus que le tri bulle pour stocker l'indice du plus grand lment, mais il utilise moins d'instructions (une seule permutation par parcours du tableau)

Le tri slection peut tre amlior en positionnant chaque parcours du tableau le plus grand et le plus petit lment, selon le mme principe que celui utilis pour le tri Boustrophdon.
dans ce cas, on fera 2 fois moins de tours de boucle tantque (on trie 2 lments chaque tour) mais chaque tour, on effectuera plus d'oprations, la complexit reste donc quadratique mais s'amliore
11

21

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri slection (3/3)


Tri par la mthode du tri slection de tableaux d'entiers gnrs alatoirement

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Le tri slection est en place et l'algorithme donn ici est stable (il serait instable si on utilisait au lieu de >)

Tri insertion (1/2)


Principe du tri insertion : on prend deux lments qu'on trie dans le bon ordre, puis un 3e qu'on insre sa place parmi les 2 autres, puis un 4e qu'on insre sa place parmi les 3 autres, etc. C'est la mthode la plus utilise pour trier des dossiers, des cartes jouer, ... Algorithme : i reprsente le nombre d'lments tris
fonction sans retour triInsertion(entier[] tab){ entier i, j, val; debut pour (i allant de 1 tab.longueur-1 pas 1) faire val <- tab[i]; j <- i; tantque ((j > 0) et (tab[j-1] > val)) faire tab[j] <- tab[j-1]; j <- j-1; fintantque tab[j] <- val; finpour fin

Tri insertion (2/2)


Complexit du tri insertion :
au pire, si le tableau est tri en ordre inverse, chaque tour de la boucle pour, on fait i tours de boucle tantque. La complexit au pire sera donc proportionnelle 1+2+...+(n-1) =n*(n-1)/2 et donc en O(n2). au mieux, si le tableau est dj tri, on fera une seule comparaison par lment, sans permutation, sauf pour le premier lment. La complexit au mieux est donc proportionnelle (n-1) et linaire. en moyenne, chaque lment sera insr au milieu de ceux dj tris, le nombre de comparaisons sera donc de 0+1+3/2+...+n/2 soit n*(n+1)/4 et la complexit moyenne est donc en O(n2).

Le tri par insertion est en place et l'algorithme donn ici est stable (il serait instable si on utilisait au lieu de >)
Remarque : le tri insertion est donc environ 2 fois plus rapide que le tri slection

31

41

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tris quadratiques
Comparaison des tris quadratiques sur des tableaux d'entiers gnrs alatoirement

Tri rapide (1/5)


Principe du tri rapide (quicksort, tri de Hoare) : on prend le premier lment (le pivot), on le met sa place en plaant sa gauche les lments plus petits que lui et sa droite les lments plus grands que lui. Puis on rpte l'opration d'une part sur le sous tableau de gauche, d'autre part sur le sous-tableau de droite. Algorithme : on partitionne le tableau autour de la valeur contenue dans la premire case, puis on appelle l'algorithme sur chacune des sous-parties. Il nous faut donc :
une fonction qui partitionne une certaine section [a,b] du tableau en plaant au dbut les lments plus petits que tab[a], puis tab[a], puis les lments plus grands ou gaux tab[a] et retourne l'indice de tab[a] dans le tableau partitionn (au dpart, a vaudra 0 et b vaudra tab.longueur-1) une fonction de tri proprement dit qui appelle la fonction prcdente puis lance des appels rcursifs sur les sous-parties

51 61

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri rapide (2/5)


fonction avec retour entier partition(entier[] tab, entier a, entier b){ entier pivot,i,temp; dbut pivot <- a; pour (i allant de a+1 b pas 1) faire si (tab[i] < tab[pivot]) alors temp <- tab[i]; tab[i] <- tab[pivot+1]; tab[pivot+1] <- tab[pivot]; tab[pivot] <- temp; pivot <- pivot+1; finsi finpour return pivot; fin // cette fonction trie les lments de tab d'indices compris entre a et b inclus fonction sans retour triRapide(entier[] tab, entier a, entier b){ entier pivot; dbut si (b > a) alors pivot <- partition(tab,a,b); triRapide(tab,a,pivot-1); triRapide(tab,pivot+1,b); finsi fin
71 81

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri rapide (3/5)


Exemple d'excution de la fonction de partitionnement :

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

70 | 17 | 2 | 268 | 415 | 45 | 45 | 102


i=1 et pivot=0 i=2 et pivot=1

17 | 70 | 2 | 268 | 415 | 45 | 45 | 102 17 | 2 | 70 | 268 | 415 | 45 | 45 | 102

i=3 et pivot=2 i=4 et pivot=2

17 | 2 | 70 | 268 | 415 | 45 | 45 | 102 17 | 2 | 70 | 268 | 415 | 45 | 45 | 102

i=5 et pivot=2

17 | 2 | 45 | 70 | 268 | 415 | 45 | 102


i=6 et pivot=3

17 | 2 | 45 | 45 | 70 | 268 | 415 | 102


i=7 et pivot=4

17 | 2 | 45 | 45 | 70 | 268 | 415 | 102


L'indice du pivot retourn est 4

Tri rapide (4/5)


Complexit du tri rapide :
la fonction de partitionnement est linaire de la forme a*n o a est une constante. au mieux, dans le cas o le partitionnement coupe toujours le tableau en deux parties gales ( 1 prs), la complexit c(n) de la fonction de tri est telle que c(n) = a*n + 2*c(n/2) + b o b est une constante. Dans ce cas, on a c(n) = O(n*log(n)). au pire, dans le cas o le partitionnement conduit systmatiquement ce qu'une des parties soit vide, la complexit c(n) de la fonction de tri est telle que c(n) = a*n + c(n-1) + b o b est une constante. Dans ce cas, on a c(n) = O(n2). en moyenne, on peut montrer que c(n) = O(n*log(n)).

Le tri rapide n'est pas optimum dans tous les cas, mais en moyenne, il est bien plus rapide que les tris quadratiques Le tri rapide est en place, mais l'algorithme donn ici n'est pas stable
91

02

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Amliorations possibles :
quand le tableau est dj un peu tri , il vaut mieux choisir comme pivot l'lment du milieu du tableau, pour quilibrer les parties

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri rapide (5/5)


fonction avec retour entier partition(entier[] tab, entier a, entier b){ entier pivot,i,temp; dbut temp = tab[a]; tab[a] = tab[(a+b)/2]; tab[(a+b)/2] = temp; pivot <- a; ... fin

quand le tableau n'est pas un peu tri , on peut dcouvrir l'lment mdian (tel que la moiti des lments du tableau sont plus petits, et la moiti plus grands, 1 prs) avec un algorithme linaire. Cette amlioration assure donc une complexit au pire en O(n*log(n)) au tri rapide. quand les parties trier sont petites, il peut tre plus rapide d'utiliser un tri par slection pour les trier car ce tri est plus rapide sur de petits tableaux ...

Tri fusion (1/3)


Principe du tri fusion : on dcoupe le tableau en deux, on trie chacune des 2 parties, puis on fusionne les parties tries en respectant l'ordre. Algorithme : il nous faut donc
une fonction qui fusionne deux sections contigues du tableau. Le plus simple est d'utiliser des tableaux supplmentaires (mais il est possible de faire du tri fusion en place). une fonction de tri proprement dit qui lance des appels rcursifs sur les sousparties puis appelle la fonction prcdente

Tri fusion (2/3)


// cette fonction fusionne les parties de tab d'indices dans [a,b] et [b+1,c], // en supposant que les lments de ces parties soient tris en ordre croissant. fonction sans retour fusion(entier[] tab,entier a, entier b, entier c){ entier i,j,k; entier[b-a+1] t1; int[c-b] t2; dbut pour (i allant de 0 t1.longueur-1 pas 1) faire t1[i] <- tab[a+i]; finpour pour (j allant de 0 t2.longueur-1 pas 1) faire t2[j] <- tab[b+1+j]; finpour i <- 0; j <- 0; k <- a; tantque (k <= c) faire si (i >= t1.longueur) alors tab[k] <- t2[j]; j <- j+1; sinon si (j >= t2.longueur) alors tab[k] <- t1[i]; i <- i+1; sinon si (t1[i] <= t2[j]) alors tab[k] <- t1[i]; i <- i+1; sinon tab[k] <- t2[j]; j <- j+1; finsi finsi finsi k++; fintantque fin
22

12

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tri fusion (3/3)


fonction sans retour triFusion(entier[] tab, entier a, entier b){ dbut si (b>a) alors triFusion(tab,a,(a+b)/2); triFusion(tab,((a+b)/2)+1,b); fusion(tab,a,(a+b)/2,b); finsi fin

Complexit du tri-fusion :
la complexit de la fusion est linaire de la forme a*n o a est une constante la complexit du tri est c(n) = c(n/2) + c(n/2) + a*n + b o b est une constante donc c(n) = O(n*log(n)) dans tous les cas

Le tri fusion est donc optimum en complexit, mais gnralement, il est moins rapide que le tri rapide, car il duplique le tableau. On peut optimiser le tri en ne dupliquant qu'une des deux parties. Le tri fusion est stable mais la version propose ici n'est pas en place (il est possible d'en crire des versions en place)
32

42

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Comparaison des tris quasilinaires sur des tableaux d'entiers gnrs alatoirement

noitammargorP te euqimhtiroglA - 2 ertsemeS - euqitamrofnI ecneciL

Tris quasilinaires

You might also like