Post on 04-Apr-2015
1
Les tris
2
Les trisTraitement de données triées
Le traitement de données déjà triées est plus rapide. Nécessaire pour le traitement séquentiel d’intervalles. Il faut trier des données à bas coût !
nb de comparaisons nb de déplacements d’éléments
3
Les trisTri selon une relation d’ordre
Besoin : attribut de tri :<nom,…>, <nom,prenom,...> generalement une cle que l’on peut comparer {<,=,>}
deplacer toute l’information :<cle,...> ou <cle,indirection>, + indirection vers l’information
4
Les trisTris simples
tri par insertion :
44,55,12,42,94,18,06,67
Algorithme :
insérer chacun des n elements à la bonne place dans le tableau creéé jusqu’ici
5
Les trisTris simples
tri par insertion :
44,55,12,42,94,18,06,674444,5512,44,5512,42,44,5512,42,44,55,9412,18,42,44,55,9406,12,18,42,44,55,9406,12,18,42,44,55,67,94
6
Les trisTris simples
tri par insertion :
#include <stdio.h> 1/2#define CN 0#define OK 1typedef int TypeEl;void triInsertion(TypeEl tab[], int n, int * err);void main() { TypeEl x[]={44,55,12,42,94,18,6,67};
int nbr,i;nbr=sizeof(x)/sizeof(TypeEl);printf("Le tableau non trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]);printf("\n");int err;triInsertion(x,nbr,&err);printf("Le tableau trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]); }
7
Les trisTris simples
tri par insertion :
void triInsertion(TypeEl tab[], int n, int * err) 2/2{ /* connu: - entree: tab, n
sortie: ----resultat: tab trie et *err = OK, si n >= 0,tab est inchange et *err = CN, sinon. hypothese: n >= 0 */int i, j;TypeEl x;if(n < 0) { *err = CN; return; }*err = OK;for(i = 1; i < n; i++) { j = i;
x = tab[i];while(j-1 >= 0 && x < tab[j-1]) { tab[j] = tab[j-1]; j--; }tab[j] = x;
}}
8
Les trisTris simples
tri par insertion :
Le tableau non trie 44 55 12 42 94 18 6 67Le tableau trie 6 12 18 42 44 55 67 94
9
Les trisTris simples
tri par insertion :
Meilleur cas : séquence triée nb de comparaisons ? O(n) nb de deplacements ? O(n)
Pire cas : séquence triée inverse nb de comparaisons ? O(n2) nb de deplacements ? O(n2)
10
Les trisTris simples
tri par sélection :
44,55,12,42,94,18,06,67
Algorithme :
remplir les cases de 1 à n avec le minimum des éléments du tableau restant
11
Les trisTris simples
tri par sélection :
44,55,12,42,94,18,06,6706,55,12,42,94,18,44,6706,12,55,42,94,18,44,6706,12,18,42,94,55,44,6706,12,18,42,94,55,44,6706,12,18,42,44,55,94,6706,12,18,42,44,55,94,6706,12,18,42,44,55,67,9406,12,18,42,44,55,67,94
12
Les trisTris simples
tri par sélection :
#include <stdio.h> 1/3#define CN 0#define OK 1typedef int TypeEl;void triSelection(TypeEl tab[], int n, int * err);void main() { TypeEl x[]={44,55,12,42,94,18,6,67};
int nbr,i;nbr=sizeof(x)/sizeof(TypeEl);printf("Le tableau non trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]);printf("\n");int err;triSelection(x,nbr,&err);printf("Le tableau trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]); }
13
Les trisTris simples
tri par sélection :
void triSelection(TypeEl tab[], int n, int * err) 2/3{ /* connu: - entrée: tab, n; sortie: - résultat: tab trié et *err = OK, si n>= 0 tab est inchangé et *err = CN, sinon. hypothese: n >= 0 */ int i, j, pos; TypeEl x; for(i = 0; i < n -1; i++) { pos = i; x = tab[i]; for(j = i + 1; j < n; j++)
{ if (tab[j] < x){ x = tab[j]; pos = j;}
}
14
Les trisTris simples
tri par sélection :
/*x est l’élément minimum du sous-tableau non trié*/ 3/3 if (x != tab[i])
{ tab[pos] = tab[i]; tab[i] = x;}
} //fin de boucle for} //fin de la fonction
Le tableau non trie 44 55 12 42 94 18 6 67Le tableau trie 6 12 18 42 44 55 67 94
15
Les trisTris simples
tri à bulles (Bubblesort) :
44,55,12,42,94,18,06,67
Algorithme :
remonter les plus petites bulles à la surface, et ce, à chaque itération
16
Les trisTris simples
tri à bulles (Bubblesort) :
44,55,12,42,94,18,06,6706,44,55,12,42,94,18,6706,44,55,12,18,42,94,6706,44,55,12,18,42,94,6706,12,44,55,18,42,94,6706,12,44,55,18,42,67,9406,12,18,44,55,42,67,9406,12,18,42,44,55,67,9406,12,18,42,44,55,67,94
17
Les trisTris simples
tri à bulles (Bubblesort) :
#include <stdio.h> 1/2#define CN 0#define OK 1typedef int TypeEl;void triBulles(TypeEl tab[], int n, int * err);void main() { TypeEl x[]={44,55,12,42,94,18,6,67};
int nbr,i;nbr=sizeof(x)/sizeof(TypeEl);printf("Le tableau non trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]);printf("\n");int err;triBulles(x,nbr,&err);printf("Le tableau trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]); }
18
Les trisTris simples
tri à bulles (Bubblesort) :
void triBulles(TypeEl tab[], int n, int * err) 2/2{ /* connu: - entrée: tab, n; sortie: - résultat: tab trié et *err = OK, si n>= 0 tab est inchangé et *err = CN, sinon. hypothese: n >= 0 int i, j, pos; TypeEl x; for(i = 1; i < n; i++) { for(j = n - 1; j >= i; j--)
{ if ( tab[j-1] > tab[j]){ x = tab[j-1]; tab[j-1] = tab[j]; tab[j] = x;}
} }}
Le tableau non trie 44 55 12 42 94 18 6 67Le tableau trie 6 12 18 42 44 55 67 94
19
Les trisTris simples
tri à bulles (Bubblesort) - amélioration
void triBulles(TypeEl tab[], int n, int * err){ int i, pos, change; TypeEl x; pos=1; //le nombre d’éléments triés après la boucle for do {
change=0; for(i = 0; i < n-pos; i++)
if ( tab[i] > tab[i+1]){ x = tab[i]; tab[i] = tab[i+1]; tab[i+1] = x; change=1;}
pos++; }while(change);}
Amélioration consiste à arrêter le processus s'il n'y a aucun échange dans une passe
20
Les trisTris simples
tri par fusion (merge sorting):
Algorithme
Fusion de deux tableaux triés en un seul plus grand, appelé récursivement sur les deux moitiés du tableau, jusqu'à une taille de tableau de 1 (ou plus, avec un tri spécifique pour petits tableaux, par exemple par échange sur des sous-tableaux de 3 éléments).
21
Les tris tri par fusion (merge sorting):
Le premier étape
Le deuxième étape
22
Les trisTris simples
tri par fusion (merge sorting):
#include <stdio.h> 1/4void merge_sort(int in[],int a,int b,int out[]);void aff_tab(int in[],int k);void merge_array(int in1[],int in2[],int n1,int n2,int out[]);int compar=0;main() { int in_tab[] = {3,1,4,1,5,9,2,6,5,4};
int n=sizeof(in_tab)/sizeof(int);int out_tab[20];printf("Le tableau non trie\n");aff_tab(in_tab,n);merge_sort(in_tab,0,n-1,out_tab);printf("Le tableau trie\n");aff_tab(out_tab,n);printf("Le nombre de comparaison est %d\n",compar);
}
Le tableau non trie3 1 4 1 5 9 2 6 5 4
Le tableau trie1 1 2 3 44 5 5 6 9Le nombre de comparaison est 22
23
Les trisTris simples
tri par fusion (merge sorting):
void aff_tab(int in[],int k) 2/4 { int i;
for(i=1;i<=k;i++)printf("%d%c",in[i-1],i%5==0?'\n':' ');
printf("\n"); }
Définition de la fonction d’affichage
24
Les trisTris simples
tri par fusion (merge sorting):
void merge_sort(int in[],int a,int b,int out[]) 3/4 { int m, out1[20], out2[20];
if(a==b) out[0]=in[a];else if(1==(b-a))
{ if ( in[a]<=in[b] ){ out[0]=in[a]; out[1]=in[b]; }
else{ out[0]=in[b]; out[1]=in[a]; }
compar++;}
else{ m=a+(b-a)/2;
merge_sort(in, a, m, out1); merge_sort(in, m+1, b, out2); merge_array(out1, out2, 1+m-a, b-m, out);
}}
Définition de la fonction merge_sort
25
Les trisTris simples
tri par fusion (merge sorting):
void merge_array(int in1[],int in2[],int n1,int n2,int out[]) 4/4 { int i=0,j=0,k=0;
while ( (i<n1) && (j<n2) ) { if(in1[i] <= in2[j]) { out[k]=in1[i]; i++; }
else { out[k]=in2[j]; j++; }k++;compar++;
} if(i !=n1) do { out[k]=in1[i]; i++;
k++; } while(i<n1); else do { out[k]=in2[j];
j++;k++;
} while(j<n2); }
Définition de la fonction merge_array
Si on a des éléments dans les deux sous-tableaux
Si on n’a pas d’éléments dans un des deux sous-tableaux
26
Les trisTris simples
tri panier (bucket sort) La grandeur de l’ensemble de base est petite, une
constante fixe m On utilise m compteurs
27
Les trisTris complexes
tri rapide (Quicksort) :
Ce tri est récursif.
On cherche à trier une partie du tableau délimitée par les indices gauche et droite. On choisit une valeur de ce sous-tableau (une valeur médiane serait idéale, mais sa recherche ralentit plus le tri
que de prendre aléatoirement une valeur, par exemple la dernière), = pivot.
28
Les trisTris complexes
tri rapide (Quicksort) : On cherche la position définitive de ce pivot,
On effectue des déplacements de valeurs de telle sorte que tous les éléments avant le pivot soient plus petits que lui, et que toutes celles après lui soient supérieures, mais sans chercher à les classer pour accélérer le processus.
On rappelle récursivement le tri de la partie avant le pivot, et de celle après le pivot.
On arrête la récursivité sur les parties à un seul élément, nécessairement triée.
L'algorithme est achevé quand les piles ne contiennent plus aucune partie de liste à être traitée par l'étape de réduction.
29
Les trisTris complexes
tri rapide (Quicksort) :
44,55,12,42,94,18,06,67
Algorithme : choisir un pivot p (élément médian) partager le tableau en 2:
Sous - tableau de gauche : éléments <= p Sous - tableau de droite : éléments > p
appel récursif avec le sous - tableau de gauche appel récursif avec le sous - tableau de droite
30
Les trisTris complexes
tri rapide (Quicksort) :
44,55,12,42,94,18,06,6744,55,12,42,94,18,06,67
44,55,12,42,94,18,06,67
06,55,12,42,94,18,44,67
06,55,12,42,94,18,44,67
06,18,12,42,94,55,44,67
06,18,12,42,94,55,44,67
31
Les trisTris complexes
tri rapide (Quicksort) : 06,18,12,42,94,55,44,67
06,12,18,42,94,55,44,67
06,12,18,42,94,55,44,67
06,12,18,42,44,55,94,67
06,12,18,42,44,55,94,67
06,12,18,42,44,55,67,94
32
Les trisTris complexes
tri rapide (Quicksort) : #include <stdio.h> 1/4
typedef int TypeEl;void swap(TypeEl *a,int l,int r);quicksort( TypeEl *a, int low, int high );void partition( TypeEl *a, int low, int high,int *pivot );void main() { TypeEl x[ ]={44,55,12,42,94,18,6,67};
int nbr,i;nbr=sizeof(x)/sizeof(TypeEl);printf("Le tableau non trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]);printf("\n");quicksort(x,0,nbr-1);printf("Le tableau trie\n");for(i=0;i<nbr;i++)
printf("%3d",x[i]); }
Le tableau non trie 44 55 12 42 94 18 6 67Le tableau trie 6 12 18 42 44 55 67 94
33
Les trisTris complexes
tri rapide (Quicksort) :
quicksort( TypeEl *a, int low, int high ) 2/4{
int pivot;/* condition terminale! */if ( high > low )
{ partition( a, low, high,& pivot ); quicksort( a, low, pivot-1 ); quicksort( a, pivot+1, high ); }}
Définition de la fonction quicksort
34
Les trisTris complexes
tri rapide (Quicksort) : void partition( TypeEl *a, int low, int high, int *pivot) 3/4
{ int left, right;TypeEl pivot_item;*pivot = (low+high)/2;pivot_item = a[*pivot];left=low;right = high;while ( left < right ) { /* deplacer le pointeur gauche tant que element < pivot */ while( a[left] < pivot_item ) left++;
/* deplacer le pointeur droite tant que element > pivot */ while( a[right] >= pivot_item ) right--; if ( left < right) swap(a,left,right);
} }
Définition de la fonction partition
35
Les trisTris complexes
tri rapide (Quicksort) :
void swap(TypeEl *a,int l,int r) 4/4 { TypeEl t;
t=a[l]; a[l]=a[r]; a[r]=t; }
Définition de la fonction d’échange
36
Les trisTris complexes
tri rapide (Quicksort) : Meilleur cas : pivot = médiane
nb de comparaisons ? O(n log n) nb de déplacements ? O(1)
37
Les trisTris complexes
tri rapide (Quicksort) : Pire cas : pivot = min. ou max.
nb de comparaisons ? O(n2) nb de déplacements ? O(n2)
38
Les trisTris complexes
tri rapide (Quicksort) : Exemple – Trier en ordre alphabétique une séquence de
chaînes de caractères entrées par clavier en utilisant la fonction standarde qsort (de la bibliothèque stdlib.h).
#include <stdio.h> 1/2#include <string.h>#include <stdlib.h>#define MAXMOTS 100#define MAXCARS 3000char espace[MAXCARS], *libre = espace;char *mots[MAXMOTS];int nbr_mots = 0;int comparer(const void *a, const void *b) {/* Les arguments de cette fonction doivent être déclarés "void *" (voyez la *//* déclaration de qsort). */
return strcmp(*(char **)a, *(char **)b);}
a et b sont des adresses de "chaînes"
39
Les trisTris complexes
tri rapide (Quicksort) : Exemple – Trier en ordre alphabétique une séquence de
chaînes de caractères entrées par clavier en utilisant la fonction standarde qsort (de la bibliothèque stdlib.h).
main() 2/2 { int i; while(puts ("Entrer une chaine\n"),gets(libre) != NULL && *libre != '\0')
{ mots[nbr_mots++] = libre;
libre += strlen(libre) + 1;}
qsort(mots, nbr_mots, sizeof(char *), comparer); for (i = 0; i < nbr_mots; i++)
printf("%s\n", mots[i]);}
40
Les trisTris complexes
tri rapide (Quicksort) - problèmes:
1. Algorithme récursif : taille de la pile =?
meilleur cas :O(log n) pire cas :O(n) en moyenne : O(log n)
Comment faire pour minimiser la taille de la pile ? empiler toujours le plus grand des 2 sous-tableaux
O(1) <= taille de la pile <= O(log n) plutot que : O(1) <= taille de la pile <= O(n)
41
Les trisTris complexes
tri rapide (Quicksort) - problèmes:1. Attention aux bornes:
3. Choix de pivot Comment choisir un bon pivot ?
Solution idéale : Trouver a chaque fois la valeur médiane du
sous - tableau a trier - sa recherche précise rend le tri plus lent que sans elle.
Solution quelquefois utilisée : Prendre par exemple trois valeurs, pour en
prendre la valeur médiane. La totalité de ces améliorations peut apporter un
gain de l'ordre de 20% par rapport à la version de base.
42
Les trisTris complexes
tri par arbre (Treesort):
Algorithme Utiliser une structure d’arbre pour trier la séquence de
clés.