06.02.2014 Views

Algorithmes de tri - UQAC

Algorithmes de tri - UQAC

Algorithmes de tri - UQAC

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Algorithmes</strong> <strong>de</strong> <strong>tri</strong><br />

1


l’utilité <strong>de</strong>s <strong>tri</strong>s<br />

Problématique:<br />

Un grand nombre <strong>de</strong> problèmes réels ont recours à la<br />

recherche d’éléments dans un vecteur (tableau). Cette<br />

recherche <strong>de</strong>vient quasiment impossible lorsqu’elle<br />

s’effectue dans un vecteur désordonné, d’où le besoin <strong>de</strong><br />

<strong>tri</strong>er les vecteurs avant d’y effectuer un traitement.<br />

Exemples:<br />

• Les mots dans un dictionnaire.<br />

• Fichiers dans un répertoire <strong>de</strong> PC.<br />

• Les CD répertoriés dans un magasin <strong>de</strong> musique.<br />

• Les sigles <strong>de</strong>s cours <strong>de</strong> Poly offert pour une session.<br />

2


Définitions<br />

Tri interne : se dit d'un algorithme qui<br />

n'utilise pas <strong>de</strong> tableau temporaire pour<br />

effectuer le <strong>tri</strong>.<br />

Tri externe : se dit d'un algorithme <strong>de</strong> <strong>tri</strong><br />

qui nécessite l'utilisation d'un tableau<br />

temporaire.<br />

3


II – Les <strong>tri</strong>s simples<br />

• Tri par sélection s<br />

• Tri bulle<br />

• Tri par insertion<br />

4


Tri par sélections<br />

Principe :<br />

• Cette technique consiste à parcourir<br />

séquentiellement le vecteur à <strong>tri</strong>er. À l'itération<br />

i, la plus petite valeur du tableau est échangée<br />

avec la valeur située dans la case d'indice i.<br />

5


Exemple d’exd<br />

exécution du <strong>tri</strong> par<br />

sélection<br />

min = [1] [2]<br />

[3] [4] [0]<br />

i = 0123<br />

10<br />

2<br />

7<br />

15<br />

8<br />

0 1 2 3 4 i<br />

6


Programmation du <strong>tri</strong> par sélections<br />

template<br />

void TriSelection( vector& Tableau, int n)<br />

{<br />

int i, j, min;<br />

T Tmp;<br />

for ( i=0 ; i


Tri en bulle<br />

Principe :<br />

• Les petits éléments du tableau « remontent »<br />

(comme <strong>de</strong>s bulles) vers le début du tableau pour<br />

atteindre leur position finale. Les plus « légers »<br />

remontent le plus rapi<strong>de</strong>ment. Une fois tous les<br />

éléments remontés, le tableau est <strong>tri</strong>é.<br />

8


Exemple d’exd<br />

exécution du <strong>tri</strong> en bulle<br />

: comparaison <strong>de</strong><br />

<strong>de</strong>ux éléments<br />

10<br />

2<br />

7<br />

15<br />

8<br />

Position <strong>de</strong> i<br />

0 1 2 3 4 i<br />

9


Programmation du <strong>tri</strong> en bulle<br />

template<br />

void TriBulle(vector& Tableau, , int n)<br />

{<br />

int i,j;<br />

T Tmp;<br />

for ( i=0; ii; j--j<br />

--)<br />

if ( Tableau[j-1]> Tableau[j])<br />

{<br />

Tmp = Tableau[j-1];<br />

Tableau[j-1] = Tableau[j];<br />

Tableau[j] = Tmp;<br />

}<br />

}<br />

10


Tri par insertion<br />

Principe :<br />

• Cette stratégie est semblable à la métho<strong>de</strong><br />

qu'utilise naturellement un joueur <strong>de</strong> cartes pour<br />

organiser sa main. À chaque étape, une partie<br />

du tableau est déjà ordonnée et une nouvelle<br />

valeur est insérée à l'endroit approprié.<br />

11


Exemple d’exd<br />

exécution par insertion<br />

10<br />

2<br />

7<br />

15<br />

8<br />

0 1 2 3 4 i<br />

12


Programmation du <strong>tri</strong> par insertion<br />

template < class T><br />

void TriInsertion(vector& Tableau, int n)<br />

{<br />

int i,j;<br />

T Tmp;<br />

for ( i=1;i


Analyse <strong>de</strong>s <strong>tri</strong>s simples<br />

Meilleur cas: tableau déjà <strong>tri</strong>é<br />

1 3 5 7 9 10 13 18 21 25<br />

Cas moyen: tableau aléatoire<br />

7 10 21 9 1 25 18 3 5 13<br />

Pire cas: tableau <strong>tri</strong>é à l’envers<br />

25 21 18 13 10 9 7 5 3 1<br />

14


Comparaison <strong>de</strong>s <strong>tri</strong>s simples<br />

Pire cas Cas moyen Meilleur cas<br />

Tri par sélection<br />

Tri en bulle<br />

Tri par insertion<br />

O ( n<br />

2 ) (<br />

2<br />

O n ) (<br />

2<br />

O n )<br />

O ( n<br />

2 ) (<br />

2<br />

O n ) (<br />

2<br />

O n )<br />

O ( n<br />

2 ) (<br />

2<br />

n )<br />

O O( n)<br />

15


mergesort<br />

Problématique :<br />

<br />

Le <strong>tri</strong> est effectué en utilisant la technique <strong>de</strong> diviser-etconquérir,<br />

en divisant le problème en <strong>de</strong>ux sousproblèmes<br />

<strong>de</strong> complexité θ ( n)<br />

résolus récursivement,<br />

offrant une complexité globale <strong>de</strong><br />

L'algorithme <strong>de</strong> <strong>tri</strong> Mergesort :<br />

( nlog2 n )<br />

1. Si le nombre d’éléments à <strong>tri</strong>er == (0 ou 1), retourner.<br />

2. Trier récursivement la première et <strong>de</strong>uxième moitié<br />

séparément.<br />

3. Regrouper les <strong>de</strong>ux parties <strong>tri</strong>ées dans un nouveau groupe<br />

<strong>tri</strong>é.<br />

θ<br />

16


MergeSort<br />

1 13 24 26 2 15 27 38<br />

Actr<br />

Bctr<br />

Cctr<br />

17


La fonction Mergesort<br />

// Routine interne : Tableau: le vecteur d’éd<br />

’éléments<br />

// tmpTab: vecteur temporaire pour les résultatsr<br />

// left, right: indices gauche et droit <strong>de</strong>s tableaux<br />

template <br />

void mergeSort(vector& Tableau, vector& tmpTab,<br />

int left, int right)<br />

{<br />

if (left < right)<br />

{<br />

int center = (left+right)/2;<br />

mergeSort(Tableau, tmpTab, left, center)<br />

mergeSort(Tableau, tmpTab, center+1, right);<br />

merge(Tableau, tmpTab, left, center+1, right);<br />

}<br />

}<br />

template // Fonction principale<br />

void mergeSort(vector& Tableau)<br />

{<br />

vector tmpTab(Tableau.size());<br />

mergeSort(Tableau,tmpTab,0,Tableau.size()-1);<br />

}<br />

18


La fonction Merge<br />

// Routine interne : Tableau: le vecteur d’éd<br />

’éléments<br />

// tmpTab: vecteur pour les résultats r<br />

du merge<br />

// leftPos: indice gauche du tableau<br />

// rightPos: indice du début d<br />

<strong>de</strong> la 2ieme <strong>de</strong>mi<br />

// rightEnd: indice droit du tableau<br />

template <br />

void merge(vector& Tableau, vector& tmpTab, int leftPos,<br />

int rightPos, int rightEnd)<br />

{<br />

int leftEnd = rightPos-1;<br />

int tmpPos = leftPos;<br />

int numElements = rightEnd – leftPos +1;<br />

//Boucle principale<br />

while( leftPos


La fonction Merge<br />

. . .<br />

while(leftPos


Le <strong>tri</strong> rapi<strong>de</strong> (Quicksort(<br />

Quicksort)<br />

Idée e générale g<br />

:<br />

Dans cet algorithme, l'exécution du <strong>tri</strong> est simplement délégud<br />

guée à une<br />

série d'appels récursifs. r<br />

Une fonction <strong>de</strong> partitionnement est d'abord<br />

appelée. e. Cette fonction choisit arbitrairement un pivot qui est utilisé<br />

pour subdiviser le tableau en <strong>de</strong>ux parties:<br />

1. une partie <strong>de</strong> gauche oùo<br />

tous les éléments ont une valeur plus petite<br />

ou égale au pivot;<br />

2. une partie <strong>de</strong> droite oùo<br />

tous les éléments ont une valeur plus gran<strong>de</strong><br />

ou égale au pivot.<br />

Par la suite, les <strong>de</strong>ux parties ainsi obtenues sont <strong>tri</strong>ées par <strong>de</strong>ux appels<br />

récursifs<br />

à la fonction <strong>de</strong> <strong>tri</strong> rapi<strong>de</strong>.<br />

En plus <strong>de</strong> la fonction principale <strong>de</strong> <strong>tri</strong> rapi<strong>de</strong>, une autre fonction est<br />

donc requise: celle qui procè<strong>de</strong><br />

à la partition du tableau.<br />

21


Quicksort : choix du pivot<br />

premier élément ?<br />

élément aléatoire?<br />

<strong>de</strong>rnier élément?<br />

élément médian?<br />

…. 7 2 9 6 1 5 4 3 …..<br />

22


La fonction Quicksort<br />

template <br />

void QuickSort(vector& tableau, int inf,<br />

int sup)<br />

{<br />

int milieu;<br />

if (sup>inf) // s'il y a au moins 2<br />

éléments<br />

{<br />

milieu = Partition(tableau, inf, sup);<br />

}<br />

}<br />

// <strong>tri</strong>er la partie <strong>de</strong> gauche<br />

QuickSort(tableau, inf, milieu);<br />

// <strong>tri</strong>er la partie <strong>de</strong> droite<br />

QuickSort(tableau, milieu+1, sup);<br />

23


Exemple d’exd<br />

exécution <strong>de</strong> Partition<br />

i<br />

Premier Pivot =<br />

appel<br />

Tab[2] = 5<br />

Quicksort(a,0,4)<br />

j<br />

11<br />

7<br />

5<br />

2<br />

9<br />

0 1 2 3 4 i<br />

24


La fonction Partition<br />

template <br />

int Partition(vector& tableau, int inf, int sup)<br />

{<br />

T pivot, tempo;<br />

int i,j;<br />

pivot = tableau[(sup+inf)/2];<br />

i = inf-1;<br />

j = sup+1;<br />

while ( i


Complexité du Quicksort<br />

Cas moyen et meilleur cas<br />

Complexité du Quicksort dans le cas moyen<br />

et dans le meilleur cas θ( nlog2 n ).<br />

Pire cas<br />

Complexité du Quicksort dans le pire cas:<br />

θ<br />

2<br />

( n )<br />

26

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!