Algorithmes de Tri

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 6

UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I.

L2 - S3

CHAPITRE 2 : ALGORITHMES DE TRI


Plan
1. Présentation
2. Tri par sélection
3. Tri par insertion
4. Tri à bulles
5. Tri fusion
6. Tri rapide

1. PRESENTATION
Le tri est sans doute un des problèmes les plus fondamentaux de l’algorithmique. Après le tri beaucoup
d’autres problèmes deviennent facile à résoudre tels que l’unicité ou la recherche.

Le tri consiste à réarranger une liste de 𝑛 objets de telle manière :


𝑋 ≤ 𝑋 ≤ ⋯ ≤ 𝑋 : Tri par ordre croissant
𝑋 ≥ 𝑋 ≥ ⋯ ≥ 𝑋 : Tri par ordre décroissant

Il existe plusieurs méthodes de tri, nous citons :


- Tri par sélection
- Tri par insertion
- Tri à bulles
- Tri par fusion
- Tri rapide
- Tri shell
- …

Dans ce qui suit, on décrit les principaux algorithmes de tri puis on analysera leur complexité temporelle.

2. TRI PAR SELECTION (SELECTION SORT)

2.1. Principe
Itérativement, le tri par sélection consiste à chercher le plus petit élément puis de le mettre au début.

Exemple

Liste initiale 42 17 13 28 14

1ère itération 13 17 42 28 14

2ème itération 13 14 42 28 17

3ème itération 13 14 17 28 42

4ème itération 13 14 17 28 42

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 12


UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I. L2 - S3

2.2. Implémentation
public void selectionSort(int[] A, int n)
{
for (int i=0;i<n-1;i++)
{ int imin=i;
for (int j=i+1;j<n;j++)
if (A[j]<A[imin]) imin=j;
swap(A,i,imin);
}
}

2.3. Complexité
Le pire et le meilleur cas sont pareils, puisque pour trouver le plus petit élément, (𝑛 − 1) itérations sont
nécessaires, pour le 2ème plus petit élément, (𝑛 − 2) itérations sont effectuées… jusqu’à l’avant dernier plus
petit élément qui nécessite 1 itération. Le nombre total d’itérations est donc :

𝑛(𝑛 − 1)
𝑖= = 𝑂(𝑛 )
2

3. TRI PAR INSERTION (INSERTION SORT)

3.1. Principe
Itérativement, on insère le prochain élément dans la partie qui a été déjà triée précédemment. La partie de
départ qui est triée est le premier élément.

Exemple

Liste initiale 42 17 13 28 14

1ère itération 17 42 13 28 14

2ème itération 13 17 42 28 14

3ème itération 13 17 28 42 14

4ème itération 13 14 17 28 42

3.2. Implémentation
public void insertionSort(int[] A, int n)
{
for (int i=1;i<n;i++)
{ int temp=A[i],j=i;
while (j>0 && A[j-1]>temp)
{ A[j]=A[j-1];j--;}
A[j]=temp;
}
}

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 13


UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I. L2 - S3

3.3. Complexité
Comme nous n’avons pas nécessairement à scanner toute la partie déjà triée, le pire et le meilleur cas sont
différents.
Meilleur cas : si le tableau est déjà trié, chaque élément est toujours inséré à la fin de la partie triée ; nous
n’avons à déplacer aucun élément. Comme nous avons à insérer (𝑛 − 1) éléments, chacun
générant seulement une comparaison, la complexité est 𝑂(𝑛).
Pire cas : si le tableau est inversement trié, chaque élément est inséré au début de la partie triée. Dans
ce cas, tous les éléments de la partie triée doivent être déplacés à chaque itération. La ième
itération génère (i-1) comparaisons et échanges de valeurs :
𝑛(𝑛 − 1)
(𝑖 − 1) = = 𝑂(𝑛 )
2

4. TRI A BULLES (BUBBLE SORT)

4.1. Principe
Parcourir le tableau en comparant deux à deux les éléments successifs et permuter s’ils ne sont pas dans
l’ordre.

Exemple
Liste initiale 42 17 13 28 14

1ère itération 13 42 17 14 28

2ème itération 13 14 42 17 28

3ème itération 13 14 17 42 28

4ème itération 13 14 17 28 42

4.2. Implémentation
public void bubbleSort(int[] A, int n)
{
for (int i=0;i<n-1;i++)
for (int j=n-1;j>i;j--)
if (A[j]<A[j-1]) swap(A,j,j-1);
}

4.3. Complexité
Globalement, c’est la même complexité que le tri par sélection. Le meilleur et le pire cas sont pareils avec une
complexité de 𝑂(𝑛²).

5. TRI FUSION (MERGE SORT)

5.1. Principe
Cet algorithme divise en deux parties égales le tableau. Après que ces deux parties soient triées (de manière
généralement récursive), elles sont fusionnées pour l’ensemble des données.

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 14


UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I. L2 - S3

Exemple
42 17 13 28 14

42 17 13 28 14

42 17 13 28 14

28 14

14 28

17 42 13 14 28

13 14 17 28 42

5.2. Implémentation
public void mergeSort(int[] A, int deb , int fin)
{
int mil;
if (deb<fin) {
mil=(deb+fin)/2; (* DIVIDE *) .......................................................... 𝑶(𝟏)
mergeSort(A,deb,mil); (* CONQUER *) ....................................................... 𝑻(𝒏/𝟐)
mergeSort(A,mil+1,fin);(* CONQUER *) ....................................................... 𝑻(𝒏/𝟐)
fusion(A,deb,mil,fin); (* COMBINE *) ....................................................... 𝑶(𝒏)
}
}

public void fusion(int[] A, int deb, int mil, int fin)


{
int n1,n2,i,j; int[] R = new int[50]; int[] L = new int[50];
n1=mil-deb+1;
n2=fin-mil;
for (i=1;i<=n1;i++) L[i]=A[deb+i-1];
for (j=1;j<=n2;j++) R[j]=A[mil+j];
L[n1+1]=9999; //Nombre très grand
R[n2+1]=9999;
i=j=1;
for (int k=deb;k<=fin;k++) {
if (L[i]<=R[j]) {A[k]=L[i];i++;}
else {A[k]=R[j];j++;}
}
}

5.3. Complexité
La complexité peut être exprimée par récurrence :
 O(1) si n  1
𝑇(𝑛) =   𝑇(𝑛) = 𝑂(𝑛𝑙𝑜𝑔 𝑛)
2T (n / 2)  O( n ) si n  1
Le tableau A sera divisé par 2 jusqu’à obtention de tableaux de taille 1, ainsi :
Taille de A : 𝑛 , 𝑛/2 , 𝑛/4, …., 𝑛/2 avec 𝑛/2 = 1  𝑝 = 𝑙𝑜𝑔 (𝑛)

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 15


UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I. L2 - S3

Puisqu’à chaque étape, une (ou plusieurs) opération(s) de fusion de l’ordre 𝑂(𝑛) est exécutée sur les sous
tableaux obtenus, on obtient donc 𝑂(𝑛𝑙𝑜𝑔 𝑛).

6. TRI RAPIDE (QUICK SORT)

6.1. Principe
L’idée de cet algorithme est de diviser le tableau en deux parties séparées par un élément appelé pivot de
telle manière que les éléments de la partie gauche soient tous inférieurs ou égaux à cet élément et ceux de la
partie droite soient tous supérieurs à ce pivot. Cette étape fondamentale du tri rapide s’appelle le
partitionnement.

Choix du pivot : Le choix idéal serait que ça coupe le tableau exactement en deux parties égales, mais
cela n’est pas toujours possible. On peut prendre le premier ou le dernier ou de
manière aléatoire,…

Partitionnement :
 On parcourt de gauche à droite jusqu’à rencontrer un élément supérieur au pivot.

 On parcourt de droite à gauche jusqu’à rencontrer un élément inférieur au pivot.

 On échange ces deux éléments.

 On recommence les parcours gauche-droite et droite-gauche jusqu’à avoir :

 Il suffit alors de mettre le pivot à la frontière par un échange

Dans ce qui suit (Exemple & implémentation) on choisit l’élément se trouvant au milieu du tableau comme
pivot.

Exemple

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 16


UEF312 : Algorithmique et Structures de Données ASD3 - Notes de cours Licence M.I. L2 - S3

6.2. Implémentation
public void quickSort(int[] A, int deb, int fin)
{
int ipivot;
if (deb<fin)
{
ipivot=partition(A,deb,fin);
quickSort(A,deb,ipivot-1);
quickSort(A,ipivot+1,fin);
}
}

public int partition(int[] A, int deb, int fin)


{
int pivot,aux,i,j;
pivot=A[(deb+fin)/2];
i=deb;j=fin;
while (i<j)
{
while (pivot>A[i]) i++;
while (pivot<A[j]) --j;
if (i<j) swap(A,i,j);
}
return j;
}

6.3. Complexité
 Cas favorable :
La meilleure chose qui puisse arriver, c'est qu'à chaque fois que la fonction Partition() est appelée, elle divise
exactement le tableau (ou le sous-tableau) en 2 parties égales.

À la première passe, les 𝑛 éléments du tableau sont comparés avec la valeur pivot pour les balancer à la
droite ou à la gauche. Il y a donc 𝑛 comparaisons. À la seconde passe il y a 2 fonctions Partition() qui
effectuent leur rôle chacune sur leur moitié de tableau. Chaque fonction doit comparer les 𝑛/2 éléments du
sous-tableau pour effectuer le balancement. Donc de fait, il y a encore 𝑛 comparaisons pour cette passe. Il en
sera de même pour les autres itérations.

Nous pouvons exprimer la complexité sous forme de récurrence :


𝑂(1) 𝑠𝑖 𝑛 = 1
𝑇(𝑛) =  𝑇(𝑛) = 𝑂(𝑛𝑙𝑜𝑔 𝑛)
2𝑇 + 𝑂(𝑛) 𝑠𝑖 𝑛 > 1

 Cas défavorable :
La pire chose qui puisse arriver, c'est qu'à chaque appel à la fonction Partition(), à cause des circonstances
de la disposition des données, celle-ci place la totalité du sous-tableau à droite ou à gauche (excluant bien
sûr l'élément pivot qui est alors à sa place définitive). Dès lors le tri rapide se transforme en un tri à bulles.

À la première passe, il y aura donc 𝑛 comparaisons. À la seconde passe il y a déjà une valeur ordonnée et un
sous-tableau de 𝑛 − 1 éléments, il y aura donc 𝑛 − 1 comparaisons effectuées par la fonction Partition(). À la
3ème passe, il y aura 𝑛 − 2 comparaisons, etc.

Pour effectuer le tri au complet, il aura donc fallu en tout 𝑛 passes. D'où la complexité:

𝑛 + (𝑛 − 1) +. . . +2 + 1 = 𝑛(𝑛 + 1)/2

Soit donc O(𝑛²) = pire cas de Quicksort. Mais il reste que la complexité en moyenne est O(𝑛log2𝑛).

USTO MB – Faculté des Mathématiques & Informatique, Département Informatique 17

Vous aimerez peut-être aussi