Vous êtes sur la page 1sur 44

Algorithmes de tri

1
Le tri est un problème fondamental de l’algorithmique
Après le tri, beaucoup de problèmes deviennent faciles à résoudre:
Unicité d’éléments: après le tri tester les éléments adjacents
Recherche d’un élément
on peut déterminer le kème plus grand élément

2
Le tri consiste à réarranger une permutation of n objets de telle manière
X ≥ X ≥ X ≥ ... ≥ X n 1 2 3 tri par ordre décroissant
n X ≤ X ≤ X ≤ ... ≤ X 1 2 3 tri par ordre croissant

Comment trier ? Il existe plusieurs solutions:

3
Tri par sélection

Répéter
1. chercher le plus grand (le plus petit) élément
2. le mettre à la fin (au début)

4
5
Tri du tableau T[ 1..n ]:
Pour (i=1 à n-1) faire
trouver l'élément minimal dans T[ i .. n ] (parcours linéaire
de T[ i .. n ] )
échanger T[i] avec cet élément
FinPour

6
Complexité :
Pour trouver le plus petit éléments, (n-1) itérations sont
nécessaires, pour le 2ème plus petit
élément, (n-2) itérations sont effectuées, .… Pour trouver le
dernier plus petit élément, 0 itération
sont effectuées. Le nombre d’itérations que l’algorithme
effectue est donc:

n 1
n ( n  1) n n 2

i 1
i 
2

2

2
7
Exercice: tri1.c
Etablir un programme en C qui effectue
le tri par sélection du tableau suivant:
1) Int t[7]={1,12,3,4,10,7,6}
2) Le tableau de même taille mais c’est l’utilisateur
qui effectue la saisie

8
Tri par insertion

Dans cet algorithme de tri , itérativement, nous insérons le


prochain élément dans la partie qui est déjà triée
précédemment. La partie de départ qui est triée est le premier
élément.

Pour chaque valeur de I [2, N], on commence avec


A[1..I-1] déjà trié et on insère A[I] dans sa propre position
tel que A[1..I] soit trié.
La recherche de la position adéquate est accomplie par un
balayage de droite vers la gauche commençant à la position I.

9
10
Pour (i=2 à n) faire
clef ←T[i]
// insérer clef dans le tableau triée T[1..i-1]:
j ← i-1
Tant que ( j ≥ 1 et clef < T[j] )
déplacer T[j] d’une position à droite
j ← j-1
FinTantque
T[j+1]← clef
FinPour

11
Exercice: tri2.c
Etablir un programme en C qui effectue
le tri par insertion du tableau suivant:
1) Int t[7]={1,12,3,4,10,7,6}
2) Le tableau de même taille mais c’est l’utilisateur
qui effectue la saisie

12
Tri à Bulles

La stratégie de cet algorithme est comme suit :


1. Parcourir le tableau en comparant deux à deux les
éléments successifs, permuter s'ils ne
sont pas dans l'ordre
2. Répéter tant que des permutation sont effectuées.

13
14
15
16
17
Exercice: tri2.c
Etablir un programme en C
qui effectue
le tri par insertion du tableau
suivant:
1) Int t[7]={1,12,3,4,10,7,6}
2) Le tableau de même taille
mais c’est l’utilisateur
qui effectue la saisie

18
#include <stdio.h>
#include<stdio.h>
void swap2(int *x, int *y)
{
int tmp;
tmp=*x;
*x=*y;
*y=tmp;
return;
}
void SortSelect(int *array,int n)
{
int i,j,lowindex=0;
for( i=0;i<n-1;i++)
{
lowindex=i;
for( j=i+1;j<n;j++)
{ if (*(array+j)>*(array+lowindex))
lowindex=j;
swap2(&(array[j]),&(array[lowindex]));
}
}
}
19
void main(void)
{
int *tab,i,n;
n=7;
int t[7]={1,12,3,4,10,7,6};
tab=t;
SortSelect(tab,n);
for(i=0;i<7;i++)
printf(" %i %i \n",i,t[i]);

20
#include <stdio.h>
#include<stdio.h>
// tri par insertion
void SortInsert(int *tab,int n)
{
int i, key, j;
for (i = 1; i < n; i++) {
key = tab[i];
j = i - 1;
while (j >= 0 && tab[j] > key) {
tab[j + 1] = tab[j];
j = j - 1;
}
tab[j + 1] = key;
}
}

21
void main(void)
{
int *tab,i,n;
n=7;
int t[7]={1,12,3,4,10,7,6};
tab=t;
SortInsert(tab,n);
for(i=0;i<7;i++)
printf(" %i %i \n",i,t[i]);

22
#include <stdio.h>
#include<stdio.h>
// tri par bulle
void swap2(int *x, int *y)
{
int tmp;
tmp=*x;
*x=*y;
*y=tmp;
return;
}
void SortBuble(int *array,int n)
{
for(int i=0;i<n-1;i++)
{

for(int j=0j<n-i-1;j++)
{ if (*(array+j)>*(array+j+1))

swap2(&(array[j]),&(array[j+1]));
}
}
}
23
void main(void)
{
int *tab,i,n;
n=7;
int t[7]={1,12,3,4,10,7,6};
tab=t;
SortBuble(tab,n);
for(i=0;i<7;i++)
printf(" %i %i \n",i,t[i]);

24
Tri shell - Principe

• C'est une amélioration du tri insertion. Il est basé sur le


constat que le tri insertion est coûteux lorsqu'il faut faire de
grands déplacements.
• On pratique donc un tri insertion en déplaçant les valeurs
d'un pas donné. On raffine ce pas jusqu'à la valeur 1.
• Lorsque le pas vaut 1 c'est le tri insertion.
• Le choix du pas est important pour les performances la
série : 1, 4, 13, 40, 121 (pas = 3.pas+1) est souvent
utilisée

25
Tri shell - Exemple
Boucle de tri avec un "pas" de 4

53 31 10 87 13 59 62 26 8 38
13 31 10 87 53 59 62 26 8 38
13 31 10 87 53 59 62 26 8 38
13 31 10 87 53 59 62 26 8 38
A remarquer que le
nombre 8 est 13 31 10 26 53 59 62 87 8 38
déplacé de deux 13 31 10 26 8 59 62 87 53 38
"pas"
8 31 10 26 13 59 62 87 53 38
8 31 10 26 13 38 62 87 53 59
26
1. void triShell(int tab[], int n) Tri shell
2. { int pas, i, j, temp; Programme
3. pas = 0;
4. while ( pas < n) // Calcul du pas
5. pas = 3*pas+1;
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17. }
18. }
27
1. void triShell(int tab[], int n) Tri shell
2. { int pas, i, j, temp; Programme
3. pas = 0;
4. while ( pas < n) // Calcul du pas
5. pas = 3*pas+1;
6. while (pas != 0) // tant que le pas est > 0
7. { pas = pas/3;
8. for(i= pas; i < n; i++)
9. { temp = tab[i]; // valeur à décaler éventuellement
10.
11.
12.
13.
14. tab[j] = temp;
15. }
16. }
17. }
28
1. void triShell(int tab[], int n) Tri shell
2. { int pas, i, j, temp; Programme
3. pas = 0;
4. while ( pas < n) // Calcul du pas
5. pas = 3*pas+1;
6. while (pas != 0) // tant que le pas est > 0
7. { pas = pas/3;
8. for(i= pas; i < n; i++)
9. { temp = tab[i]; // valeur à décaler éventuellement
10. j = i;
11. while((j>(pas-1)) && (tab[j-pas]> temp))
12. { tab[j] = tab[j-pas]; // échange des valeurs
13. j = j-pas;
14. }
15. tab[j] = temp;
16. }
17. }
18. }
29
Tri rapide

 Le tri rapide est l’une des méthodes les plus efficaces et les plus utilisées.
 Principalement, l’algorithme du tri rapide est une simple application du
principe “diviser pour conquérir”.
 Pour appliquer cet algorithme sur un tableau A, on doit d’abord partitionner
le tableau en un sous-tableau gauche et un sous-tableau droit, tels que
chaque élément du sous-tableau gauche <= tout élément du sous-tableau droit.
 Ensuite on applique de nouveau l’algorithme aux sous-tableaux gauche et
droit, ainsi on aura trié le tableau A.
 Étant donné que la dernière phrase peut être implantée par deux appels
récursifs de QuickSort, on va se concentrer d’avantage sur la phase de
partitionnement.
45
Tri rapide

 Le partitionnement commence en sélectionnant un élément dans A[1..N].


L’élément choisi est nommé pivot, soit l’élément du milieu du tableau.
 Si on commence avec le tableau A[1..14] suivant:
19 56 28 101 47 16 39 54 27 18 92 45 61 72
 Le pivot est l’élément 39, milieu du tableau. Maintenant, on veut
déplacer tous les éléments inférieurs à 39 à gauche du 39 et tous les
éléments plus grand que 39 à droite du 39. Les éléments égaux à 39
peuvent être à gauche ou à droite.
 Les tailles des deux parties résultantes ne sont pas nécessairement
égales.
.
46
Tri rapide

 Étape 1 : Nous avons :


Pivot

19 56 28 101 47 16 39 54 27 18 92 45 61 72

U
pCounter
DownCounter

 Étape 2 : UpCounter est incrémenté et s’arrête à 56


DownCounter est décrémenté et s’arrête à 18
Pivot

19 56 28 101 47 16 39 54 27 18 92 45 61 72

UpCounter
DownCounter
47
Tri rapide

 Étape 3 : 18 et 56 sont
interchangés
UpCounter est incrémenté et DownCounter est décrémenté
Pivot

19 18 28 101 47 16 39 54 27 56 92 45 61 72

UpCounter
DownCounter

 Étape 4 : UpCounter est incrémenté et s’arrête à 101


DownCounter est décrémenté et s’arrête à
27
Pivot
19 18 28 101 47 16 39 54 27 56 92 45 61 72

UpCounter
DownCounter

48
Tri rapide

 Étape 5 : 27 et 101 sont interchangés


UpCounter est incrémenté et DownCounter est décrémenté
Pivot

19 18 28 27 47 16 39 54 101 56 92 45 61 72

UpCounter
DownCounter

 Étape 6 : UpCounter est incrémenté et s’arrête à 47


DownCounter est décrémenté et s’arrête à 39
Pivot

19 18 28 27 47 16 39 54 101 56 92 45 61 72

UpCounter
DownCounter
49
Tri rapide

 Étape 7 : 37 et 49 sont interchangés


UpCounter est incrémenté et DownCounter est décrémenté
Pivot

19 18 28 27 39 16 47 54 101 56 92 45 61 72

UpCounter
DownCounter

 Étape 8 : UpCounter est incrémenté et s’arrête à 47


DownCounter reste à 16
Pivot

19 18 28 27 39 16 47 54 101 56 92 45 61 72

UpCounter

50 DownCounter
Tri rapide

 Puisque UpCounter est supérieur à DownCounter et étant donné que


chaque élément a été comparé à l’élément pivot, aucun « swap »
n’est alors effectué.
 La partition gauche va de 1 à 6 (du début à DownCounter)
 La partition droite va de 7 à 14 (de UpCounter à la fin)

51
•Tri rapide

 Étape 1 de la partition A[1..6] : Le pivot est 28.


• Pivot
19 18 28 27 39 16

UpCounter
DownCounter

 Étape 2 : UpCounter est incrémenté et s’arrête à 28


DownCounter est décrémenté et s’arrête à 16
Pivot

19 18 28 27 39 16

UpCounter DownCounter

52
Tri rapide

 Étape 3 : 28 et 16 sont interchangés


UpCounter est incrémenté et DownCounter est décrémenté
Pivot

19 18 16 27 39 28

UpCounter
DownCounter
 Étape 4 : UpCounter est incrémenté et s’arrête à 39
DownCounter est décrémenté et s’arrête à 27
Pivot

19 18 16 27 39 28

UpCounter
DownCounter

38
Tri rapide

 Puisque UpCounter est supérieur à DownCounter et étant donné que


chaque élément a été comparé à l’élément pivot, aucun « swap »
n’est alors effectué.
 La partition gauche va de 1 à 4 (du début à DownCounter)
 La partition droite va de 5 à 6 (de UpCounter à la fin)

39
•3.2.4 Tri rapide

 Étape 1 de la partition A[1..4] : Le pivot est 18.


• Pivot
19 18 16 27

UpCounter
DownCounter

 Étape 2 : UpCounter est incrémenté et s’arrête à 19


DownCounter est décrémenté et s’arrête à 16
Pivot

19 18 16 27

UpCounter
DownCounter

40
3.2.4 Tri rapide

 Étape 3 : 19 et 16 sont interchangés


UpCounter est incrémenté et DownCounter est décrémenté
Pivot

16 18 19 27

UpCounter
DownCounter
 Étape 4 : UpCounter est incrémenté et s’arrête à 19
DownCounter est décrémenté et s’arrête à 16
Pivot

16 18 19 27

UpCounter
DownCounter

41
3.2.4 Tri rapide

 Le sous-tableau gauche consiste en A[1..1], et le sous-tableau droit


consiste en A[3..4].
 Étant donné que l’élément A[2] est déjà à sa place, donc on ne
s’intéresse plus à cet élément. A[1..1] est déjà trié.
 Il suffit de “QuickSort” A[3..4], A[5..6] et A[7..14].

42
Tri rapide

QuickSort()
{
DoQuickSort(1, n);
} /* Fin de QuickSort */

DoQuickSort(first, last)
{
if (last > first) {
Partition(first, last, leftLast, rightFirst);
DoQuickSort(first, leftLast);
DoQuickSort(rightFirst, last);
}
} /* Fin de DoQuickSort */

43
Tri rapide

Partition(first, last, leftLast, rightLast)


{
UpCounter = first;
DownCounter = last;
Pivot = A[(first +
last) / 2];

/* Mettre
A[first ..
UpCounter - 1] <=
Pivot <=
A[DownCounter + 1.. last] && UpCounter > DownCounter*/
do{
while (A[UpCounter] < Pivot) UpCounter++;
while (A[DownCounter] > Pivot) DownCounter --;
if (UpCounter <=DownCounter)
Swap A[UpCounter] avec A[DownCounter] et
avancer les compteurs;
} while (!(UpCounter > DownCounter));

leftLast =
44 DownCounter;

Vous aimerez peut-être aussi