algorithme et structure de données

67
Algorithme et structure de données IUP1 Miage

Upload: miyoko

Post on 30-Jan-2016

36 views

Category:

Documents


1 download

DESCRIPTION

Algorithme et structure de données. IUP1 Miage. Tableau à une dimension. Tableau de trois caractères {’u’, ’b’, ’c’} t[0] t[1] t[2] char[] t={’u’, ’b’, ’c’}; Tableau de trois entiers int[] t={4, 100, 21};. Déclaration d’un tableau. // déclaration char[] t ; - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Algorithme et structure de données

Algorithme et structure de données

IUP1 Miage

Page 2: Algorithme et structure de données

Tableau à une dimension

Tableau de trois caractères

{’u’, ’b’, ’c’}

t[0] t[1] t[2]

char[] t={’u’, ’b’, ’c’};

Tableau de trois entiers

int[] t={4, 100, 21};

Page 3: Algorithme et structure de données

Déclaration d’un tableau

// déclaration

char[] t ;

// création sans initialisation

t=new char[3] ;

// création avec initialisation

t={’u’,’b’,’c’};

Page 4: Algorithme et structure de données

Parcourir un tableau

char[] t = new char[3] ;

for(int i=0 ; i< t.length ; i++){

t[i]=Console.readChar(”? ”);

}

for(int i=0 ; i< t.length ; i++){

t[i]=t[i]+1;

}

for(int i=0 ; i< t.length ; i++){

S.o.p(t[i]);

}

Page 5: Algorithme et structure de données

Cryptographie : Codage de César

Discipline incluant les principes, les moyens et les méthodes de transformation des données, dans le but de masquer leur contenu, d'empêcher leur modification ou

leur utilisation illégale

Décaler les lettres de l'alphabet de trois crans vers la gauche

ABCDEFGHIJKLMNOPQRSTUVWXYZDEFGHIJKLMNOPQRSTUVWXYZABC

AVE CAESAR

Page 6: Algorithme et structure de données

Cryptographie : Codage de César

Discipline incluant les principes, les moyens et les méthodes de transformation des données, dans le but de masquer leur contenu, d'empêcher leur modification ou

leur utilisation illégale

Décaler les lettres de l'alphabet de trois crans vers la gauche

ABCDEFGHIJKLMNOPQRSTUVWXYZDEFGHIJKLMNOPQRSTUVWXYZABC

AVE CAESARDYH FDHVDU

Page 7: Algorithme et structure de données

Crypter un message

void crypter(char [] mess) {

?????

}

void deCrypter(char [] mess) {

?????

}

Page 8: Algorithme et structure de données

Crypter un message

void crypter(char [] mess) {

char aux ;

for(int i=0; i<mess.length; i++) {

aux = (char) (mess[i]+3) ;

if (aux > 'z') aux=(char)(aux - 26);

mess[i]=aux;

}

}

Page 9: Algorithme et structure de données

Décrypter un message

void deCrypter(char [] mess) {

char aux ;

for(int i=0; i<mess.length; i++) {

aux = (char)(mess[i]-3) ;

if (aux < 'a') aux=(char)(aux + 26);

mess[i]=aux;

}

}

Page 10: Algorithme et structure de données

Crypter / décrypter …

Chiffrer le message "OUI" avec un décalage de 10

Page 11: Algorithme et structure de données

Chercher un élément dans un tableau

int indexOf(char[] t, char c){

int i=0;

while(i<t.length && t[i]!=c) i++;

if (i==t.length)

return -1;

else

return i;

}

Page 12: Algorithme et structure de données

Tableau à deux dimensions

Notion mathématique de matrice Tableau de tableaux

u b c t[0][0] t[0][1] t[0][2]

x y z t[1][0] t[1][1] t[1][2]

a z e t[2][0] t[2][1] t[2][2]

Page 13: Algorithme et structure de données

Déclaration d’un tableau

// déclaration

char[][] t ;

// création sans initialisation

t=new char[3][3] ;

// création avec initialisation

t={{’u’,’b’,’c’},

{’x’,’y’,’z’},

{’a’,’z’,’e’}} ;

Page 14: Algorithme et structure de données

Parcourir un tableau

char[][] t = new char[3][3] ;

for(int l=0 ; l<3 ; l++){

for(int c=0 ; c<3 ; c++){

t[l][c]=Console.readChar(”? ”);

}

}

Page 15: Algorithme et structure de données

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

B B C D E F G H I J K L M N O P Q R S T U V W X Y Z A

C C D E F G H I J K L M N O P Q R S T U V W X Y Z A B

D D E F G H I J K L M N O P Q R S T U V W X Y Z A B C

E E F G H I J K L M N O P Q R S T U V W X Y Z A B C D

F F G H I J K L M N O P Q R S T U V W X Y Z A B C D E

G G H I J K L M N O P Q R S T U V W X Y Z A B C D E F

H H I J K L M N O P Q R S T U V W X Y Z A B C D E F G

I I J K L M N O P Q R S T U V W X Y Z A B C D E F G H

J J K L M N O P Q R S T U V W X Y Z A B C D E F G H I

K K L M N O P Q R S T U V W X Y Z A B C D E F G H I J

L L M N O P Q R S T U V W X Y Z A B C D E F G H I J K

M M N O P Q R S T U V W X Y Z A B C D E F G H I J K L

N N O P Q R S T U V W X Y Z A B C D E F G H I J K L M

O O P Q R S T U V W X Y Z A B C D E F G H I J K L M N

P P Q R S T U V W X Y Z A B C D E F G H I J K L M N O

Q Q R S T U V W X Y Z A B C D E F G H I J K L M N O P

R R S T U V W X Y Z A B C D E F G H I J K L M N O P Q

S S T U V W X Y Z A B C D E F G H I J K L M N O P Q R

T T U V W X Y Z A B C D E F G H I J K L M N O P Q R S

U U V W X Y Z A B C D E F G H I J K L M N O P Q R S T

V V W X Y Z A B C D E F G H I J K L M N O P Q R S T U

W W X Y Z A B C D E F G H I J K L M N O P Q R S T U V

X X Y Z A B C D E F G H I J K L M N O P Q R S T U V W

Y Y Z A B C D E F G H I J K L M N O P Q R S T U V W X

Z Z A B C D E F G H I J K L M N O P Q R S T U V W X Y

Page 16: Algorithme et structure de données

Créer le tableau alphabet

char[][] alphabet =new char[26][26] ;

void initAlphabet(){ char debut='a', lettre ; for(int ligne=0;ligne<26;ligne++){ ???; for(int colonne=0;colonne<26;colonne++) { alphabet[ligne][colonne]= ???; if (lettre<'z') ???; else ???; } ???; }}

Page 17: Algorithme et structure de données

Créer le tableau alphabet

char[][] alphabet =new char[26][26] ;

void initAlphabet(){ char debut='a', lettre ; for(int ligne=0;ligne<26;ligne++){ lettre=debut; for(int colonne=0;colonne<26;colonne++) { alphabet[ligne][colonne]=lettre; if (lettre<'z') lettre ++; else lettre='a'; } debut++; }}

Page 18: Algorithme et structure de données

Carré de Vigenère (1525-1596)

Pour coder - ou décoder - un texte, on utilise– un mot clef– le tableau carré constitué de 26 alphabets

décalés

Et on code lettre à lettre : chiffré = clair + clef

Page 19: Algorithme et structure de données

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

B B C D E F G H I J K L M N O P Q R S T U V W X Y Z A

C C D E F G H I J K L M N O P Q R S T U V W X Y Z A B

D D E F G H I J K L M N O P Q R S T U V W X Y Z A B C

E E F G H I J K L M N O P Q R S T U V W X Y Z A B C D

F F G H I J K L M N O P Q R S T U V W X Y Z A B C D E

G G H I J K L M N O P Q R S T U V W X Y Z A B C D E F

H H I J K L M N O P Q R S T U V W X Y Z A B C D E F G

I I J K L M N O P Q R S T U V W X Y Z A B C D E F G H

J J K L M N O P Q R S T U V W X Y Z A B C D E F G H I

K K L M N O P Q R S T U V W X Y Z A B C D E F G H I J

L L M N O P Q R S T U V W X Y Z A B C D E F G H I J K

M M N O P Q R S T U V W X Y Z A B C D E F G H I J K L

N N O P Q R S T U V W X Y Z A B C D E F G H I J K L M

O O P Q R S T U V W X Y Z A B C D E F G H I J K L M N

P P Q R S T U V W X Y Z A B C D E F G H I J K L M N O

Q Q R S T U V W X Y Z A B C D E F G H I J K L M N O P

R R S T U V W X Y Z A B C D E F G H I J K L M N O P Q

S S T U V W X Y Z A B C D E F G H I J K L M N O P Q R

T T U V W X Y Z A B C D E F G H I J K L M N O P Q R S

U U V W X Y Z A B C D E F G H I J K L M N O P Q R S T

V V W X Y Z A B C D E F G H I J K L M N O P Q R S T U

W W X Y Z A B C D E F G H I J K L M N O P Q R S T U V

X X Y Z A B C D E F G H I J K L M N O P Q R S T U V W

Y Y Z A B C D E F G H I J K L M N O P Q R S T U V W X

Z Z A B C D E F G H I J K L M N O P Q R S T U V W X Y

Clair HELLOWORLDClef ECSECSECSEChiffré LGDPQOSTDH

Page 20: Algorithme et structure de données

Carré de Vigenère (1525-1596)

Clair HELLOWORLDClef ECSECSECSEChiffré LGDPQOSTDH

Page 21: Algorithme et structure de données

Crypter/décrypter un message

void crypter(char[] mess, char[] clef) {

int l, c ;

for(int i=0; i<mess.length; i++) {

???

}

}

void deCrypter(char[] mess, char[] clef) {

for(int i=0; i<mess.length; i++){

???

}

}

Page 22: Algorithme et structure de données

Crypter un message

void crypter(char[] mess, char[] clef) {

int l, c ;

for(int i=0; i<mess.length; i++) {

l=clef[i]-'a';

c=mess[i]-'a';

mess[i]=alphabet[l][c];

}

}

Page 23: Algorithme et structure de données

Décrypter un message

void deCrypter(char[] mess, char[] clef) {

for(int i=0; i<mess.length; i++){

mess[i]=(char)('a'+

indexOf(tabApha[clef[i]-'a'],mess[i]));

}

}

Page 24: Algorithme et structure de données

Codage de Hill

Coder simultanément des groupes de 2 lettres! Remplacer chaque lettre par son ordre dans l'alphabet :

A devient 0, B devient 1,..., Z devient 25 Calculer pour chaque bloc de 2 nombres à coder x1x2,

les combinaisons linéaires : y1 = ax1+bx2y2 = cx1+dx2

Ramener les résultats y1 et y2 dans l’intervalle 0..25 en prenant leur reste dans la division par 26

Transformer y1 et y2 en lettres

Le choix de la clé correspond ici au choix des quatre entiers a,b,c,d

Page 25: Algorithme et structure de données

Codage de Hill (main)

void main(String str []) { // on suppose que le message a un nombre pair de caracteres char[] message= {'e','l','e','c','t','i','o','n'} ; int[] clef = {1,1,5,1}; if (! clefValide(clef)) S.o.p("LA CLEF N'EST PAS VALIDE !"); else { S.o.p("MESSAGE EN CLAIR : ");S.o.p(message); crypter(message,clef); S.o.p("MESSAGE CRYPTER : ");S.o.p(message); deCrypter(message,clef); S.o.p("MESSAGE DECRYPTER : ");S.o.p(message); } }

Page 26: Algorithme et structure de données

Codage de Hill (crypter)

void crypter(char[] message, int[] clef) {

int taille=message.length ;

int[] x = new int[taille] ; int[] y = new int[taille];

for(int i=0; i<taille; i++) x[i]=message[i]-'a';

for(int i=0; i<taille/2; i++) {

y[2*i] =(clef[0]*x[2*i]+clef[1]*x[2*i+1])%26 ;

y[2*i+1]=(clef[2]*x[2*i]+clef[3]*x[2*i+1])%26 ;

}

for(int i=0; i<taille; i++) message[i] =(char) (y[i]+'a');

}

Page 27: Algorithme et structure de données

Codage de Hill (decrypter)

boolean clefValide(int[] clef){ int det=determinant(clef) ; // une clef est valide ssi

// son determinant est premier avec 26 return (pgcd(det,26)==1) ;}

void deCrypter(char[] message, int[] clef) { crypter(message, inverserClef(clef)); }

Page 28: Algorithme et structure de données

Codage de Hill (decrypter)

int[] inverserClef(int[] clef) { int[] iClef= new int[clef.length]; int det =determinant(clef) ; int idet=iDeterminant(clef); iClef[0]=(clef[3]*idet)%26 ; // obtenir une valeur dans l'intervalle [0..25] int d=-clef[1]*idet ; while (d<0) {d=d+26;} iClef[1]=d%26; // obtenir une valeur dans l'intervalle [0..25] d=-clef[2]*idet ; while (d<0) {d=d+26;} iClef[2]= d%26; iClef[3]=(clef[0]*idet)%26 ; return iClef ; }

Page 29: Algorithme et structure de données

Codage de Hill (decrypter)

int iDeterminant(int[] clef){

int d=determinant(clef);

// calculer l'inverse de d dans Z/26Z

// c'est a dire trouver un nombre id

// tel que d*id=1+k*26

int id=1 ; while ((d*id)%26 !=1) id++;

return id ;

}

Page 30: Algorithme et structure de données

Voici mon tableau [I@18c3679 !!!!

void main(String[] args) {int[] tab = {5, 2, 6};S.o.p("Voici mon tableau" + tab);

}

[ --> TableauI --> integer@ --> Adresse18c3679 adresse en hexadécimal

Page 31: Algorithme et structure de données

Affection de tableaux

void main(String[] args){

int[] t1 = {5, 2, 6};

int[] t2;

t2 = t1;

S.o.p("Tableaux "+t1+","+t2);

}

Page 32: Algorithme et structure de données

Affection de tableaux

void main(String[] args){

int[] t1 = {5, 2, 6};

int[] t2;

t2 = t1;

S.o.p("Tableaux "+t1+","+t2);

}

Tableaux [I@18c3679 , [I@18c3679

Page 33: Algorithme et structure de données

1 tableau ou 2 tableaux ?

void main(String[] args){

int[] t1 = {5, 2, 6};

int[] t2 = t1;

t2[1] = 8;

S.o.p(t1[1]);

}

Page 34: Algorithme et structure de données

1 tableau ou 2 tableaux ?

void main(String[] args){

int[] t1 = {5, 2, 6};

int[] t2 = t1;

t2[1] = 8;

S.o.p(t1[1]);

}

8

Page 35: Algorithme et structure de données

Egalité de tableaux !

void main(String[] args){int[] t1 = {5, 2, 6};int[] t2 = new int[t1.length];for(byte i = 0; i < t1.length; i++){

t2[i] = t1[i];S.o.p(t1[i]+" ? "+t2[i]);

}S.o.p(t1 == t2);

}

Page 36: Algorithme et structure de données

Egalité de tableaux !

void main(String[] args){int[] t1 = {5, 2, 6};int[] t2 = new int[t1.length];for(byte i = 0; i < t1.length; i++){

t2[i] = t1[i];S.o.p(t1[i]+" ? "+t2[i]);

}S.o.p(t1 == t2);

}

5 ? 5 2 ? 2 6 ? 6false

Page 37: Algorithme et structure de données

Trier un tableau …

Réorganiser une collection d'objets selon un ordre déterminé– Les objets à trier font partis d'un ensemble muni

d'une relation d'ordre total

Méthode de tri indépendamment de la fonction d'ordre– la seule opération nécessaire est de pouvoir

comparer tout couple d'objets

Page 38: Algorithme et structure de données

Caractéristiques d'un tri

Complexité algorithmique dans le pire des cas : le nombre d'opérations effectuées dans le pire des cas

pour trier un ensemble de n éléments

Complexité en moyenne : le nombre d'opérations effectuées en moyenne pour trier

un ensemble de n éléments

Page 39: Algorithme et structure de données

Comment représenter la complexité ?

Soit n la taille du tableau à trier Complexité en O(n) (complexité linéaire) :

il faut 2 fois plus de temps pour trier n*2 éléments que n

il faut 10 fois plus de temps pour trier n*10 éléments que n

Complexité en O(n²)il faut 2² fois plus de temps pour trier n*2 éléments que n

il faut 10² fois plus de temps pour trier n*10 éléments que n

O(n) << O(n log n) << O(n²)

Page 40: Algorithme et structure de données

Caractéristiques d'un tri

Mémoire nécessaire :hormis la mémoire nécessaire pour stocker les éléments

à trier, l'algorithme nécessite-t-il une quantité de mémoire supplémentaire dépendant du nombre d'éléments à trier ?

Stabilité :

lorsque deux éléments sont équivalents pour la relation d'ordre, conserver l'ordre dans lequel ces deux éléments se trouvaient avant le tri

Page 41: Algorithme et structure de données

Tri par Insertion

Principe : – c'est le tri que l’on utilise quand on a des dossiers à

classer– On prend un dossier et on le met à sa place parmi les

dossiers déjà triés– Puis on recommence avec le dossier suivant

Page 42: Algorithme et structure de données

Pour procéder à un tri par insertion, il suffit de …

Parcourir le tableau : on prend les éléments dans l'ordre

Comparer chaque élément avec les éléments précédents jusqu'à trouver sa place

Décaler les éléments du tableau pour insérer l'élément considéré à sa place dans la partie déjà triée

Page 43: Algorithme et structure de données

Tri par Insertion : exemple

Original : 3 9 6 1 2

insérons 9 : 3 9 6 1 2

insérons 6 : 3 6 9 1 2

insérons 1 : 1 3 6 9 2

insérons 2 : 1 2 3 6 9

Page 44: Algorithme et structure de données

Tri par insertion (algorithme)

void main(String[] args){

int[] tab={2,7,1,8,3,0,1};

afficherTableau(tab);

triInsertion(tab);

afficherTableau(tab);

}

Page 45: Algorithme et structure de données

Tri par insertion (version 1)

void triInsertion(int[] t){ int taille=t.length ,j , aux ; for(int i=1;i<taille;i++){

// on commence à 1 // inserer t[i] dans t[0..i-1] j=0 ; while (t[j]<t[i]) j++ ; // t[j]>=t[i] // decalage vers la droite sur t[j-1..i] aux = t[i]; for(int k=i;k>j;k--) t[k]=t[k-1]; t[j]=aux ; }}

Page 46: Algorithme et structure de données

Propriétés du Tri par Insertion

Ne nécessite par de connaître (stoker) tous les éléments des le début

Soit n le nombre d’éléments à trier

Le nombre de comparaisons nécessaires est de l'ordre de n²/4

Le nombre moyen d'échanges est de l'ordre de n²/2

Le pire cas est obtenu avec un tableau en ordre inverse

le meilleur cas avec un tableau déjà ordonné

Intéressant dans le cas où le tableau est déjà presque ordonné

Page 47: Algorithme et structure de données

Décalages en même temps que la recherche du point d’insertion

void triInsertion2(int[] t){

int taille=t.length, j , aux ;

for(int i=1;i<taille;i++) { //on commence à 1

aux = t[i];

j=i-1 ;

while (j>=0 && t[j]>aux) {t[j+1]=t[j];j--;}

// j==-1 || t[j]<=aux

t[j+1]=aux;

}

}

Page 48: Algorithme et structure de données

Tri par insertion en réalisant des échanges (version 3)

void triInsertion3(int[] t){ int taille=t.length, j , aux ; for(int i=1;i<taille;i++){ //on commence à 1 aux = t[i]; j=i-1 ; while (j>=0 && t[j]>aux) {echanger(t,j+1,j);j--;} } }

Page 49: Algorithme et structure de données

Tri par sélection

Rechercher le plus petit que l'on va replacer à sa position finale c'est-à-dire en premier,

puis rechercher le second plus petit que l'on va replacer également à sa position finale c'est-à-dire en second,

etc, jusqu'à ce que le tableau soit entièrement trié

Page 50: Algorithme et structure de données

Tri par sélection : exemple

Original : 3 9 6 1 2

plus petit est 1 : 1 9 6 3 2

plus petit est 2 : 1 2 6 3 9

plus petit est 3 : 1 2 3 6 9

plus petit est 6 : 1 2 3 6 9

Page 51: Algorithme et structure de données

Propriétés du tri par sélection

Soit n le nombre d’éléments à trier

Nombre de comparaisons nécessaires pour un tri est de n(n-1)/2

Nombre d'échanges est de l'ordre de n

Page 52: Algorithme et structure de données

Sélectionner pour trierpublic static void main(String[] args){

int[] tab = {-2, 0, 8 ,7 ,1, -5, 12, 10, 25, 5} ; final int N=tab.length ; int indMin ; int aux ;// Trier tab[0..N-1]for(int k=0 ; k<N-1 ; k++){

// chercher la place IndMin du plus petit élément// du sous tableau tab[k..N-1]indMin=k ;for(int j=k+1 ; j<N ; j++) {

if(tab[j] < tab[indMin]) indMin=j;}// échanger tab[indMin] avec tab[k]aux = tab[indMin];tab[indMin] = tab[k];tab[k] = aux;

}}

Page 53: Algorithme et structure de données

Comparaison des tris

Les tris par Sélection et par Insertion ont une efficacitéSemblable

Ils ont chacun une boucle externe qui parcourt tous leséléments, et une boucle interne qui compare les valeurs dela boucle externe avec presque toutes les valeurs de la liste

Donc approximativement n2 comparaisons sont nécessairespour trié une liste de taille n

Ces tris sont de l’ordre de n2

D’autres tris sont plus efficace : ordre de n log2 n

Page 54: Algorithme et structure de données

Tri à Bulles (bubble sort)

L'idée est de parcourir le tableau autant fois que nécessaire en échangeant 2 à 2 les éléments consécutifs qui ne sont pas dans le bon ordre.

c'est-à-dire si t[j-1] > t[j], alors on échange t[j-1] et t[j]

Page 55: Algorithme et structure de données

Tri à Bulles : les éléments les plus légers remontent vers la surface

Après le premier passage, le plus grand élément se trouve rangé en haut du tableau, on peut donc l'exclure dans l'itération suivante

Le même raisonnement s'applique sur les itérations suivantes : à chaque itération on diminue de 1 la taille de la partie à traiter du tableau

Plusieurs élément du « haut » du tableau peuvent se trouver rangés dans l'ordre ; on peut donc optimiser le traitement en s'arrêtant au dernier élément déplacé de l'itération précédente, ce qui peut être fait en ajoutant l'instruction

Page 56: Algorithme et structure de données

Tri à Bulles : exemple

23 10 75 5 37 49 53

10 23 75 5 37 49 53

10 23 5 75 37 49 53

10 23 5 37 75 49 53

10 23 5 37 49 75 53

10 23 5 37 49 53 75

Page 57: Algorithme et structure de données

Tri Bulles

void triBulles(int[] t){ int haut=t.length-1, while (haut>0) { for(int j=0 ; j<haut ; j++){

if(t[j]>t[j+1]) {echanger(t, j, j+1);} } haut--; }}

Page 58: Algorithme et structure de données

Permuter 2 éléments dans un tableau

void echanger(int[] t,int i,int j){

int aux =t[i];

t[i]=t[j];

t[j]=aux;

}

Page 59: Algorithme et structure de données

Complexité du tri à bulles

Pour chaque position, il faut parcourir en moyenne la moitié du tableau (au début tout le tableau, puis tout moins un élément, puis tout moins 2 éléments, puis ..., puis les 3 derniers éléments, puis les 2 dernières)

Ce qui nous fait n parcours, avec pour chaque parcours n / 2 opérations : au total, n² / 2 opérations (un petit peu moins si l'algorithme s'arrête avant), soit une complexité O (n²)

Page 60: Algorithme et structure de données

Tri par comptage de fréquence

int[] tab={2,5,5,7,9,2,3,2,0,9};

// on suppose les valeurs de tab dans 0..9

int[] freq= new int[10]; // valeurs de 0 à 9 Fréquences des valeurs de tab

freq={1,0,3,1,0,2,0,1,0,2} Fréquences cumulées des valeurs de tab

freq={1,1,4,5,5,7,7,8,8,10}

Connaissant freq on peut trier tab en un seul passage !

Page 61: Algorithme et structure de données

Tri par comptage de fréquence

void triComptage(int[] t, int k){ // t prend ses valeurs dans 0..k int[] f=new int[k+1]; int n=t.length ; int[] r=new int[n]; for(int i=0 ; i<k+1 ; i++) f[i]=0 ;

// remplir f avec les frequences for(int j=0 ; j<n ; j++) f[t[j]]++ ;

// remplir f avec les frequences cumulees for(int i=1 ; i<k+1 ; i++) f[i]=f[i] + f[i-1] ; // trier t dans r

…}

Page 62: Algorithme et structure de données

Tri par comptage de fréquence

void triComptage(int[] t, int k){ // t prend ses valeurs dans 0..k int[] f=new int[k+1]; int n=t.length ; int[] r=new int[n];

… // trier t dans r

for (int j=n-1 ; j>=0 ; j--) { r[f[t[j]]-1]=t[j]; f[t[j]]-- ; } // recopier r dans t for(int j=0 ; j<n ; j++) t[j]=r[j] ;}

Page 63: Algorithme et structure de données

Tri rapide (quicksort) Hoare (1962)

1. Choisir un élément pivot PT[0].. T[k-1] T[k] T[K+1]..T[N]

2. Partitionner le tableau autour du pivot P– Tous les éléments avant P sont plus petits que P

T[0]..T[k-1] <= P

– Tous les éléments après P sont plus grands que PP < T[K+1]..T[N]

3. Recommencer– sur T[0]..T[k]

– sur T[K+1]..T[N]

Page 64: Algorithme et structure de données

Tri rapide (quicksort) Hoare (1962)

1. Choisir un élément pivot

{4,3,9,1,0,5,6,3,8,2};

2. Partitionner le tableau autour du pivot P

{2,3,3,1,0,4,6,5,8,9}

Tous les éléments avant P sont plus petits que P

Tous les éléments après P sont plus grands que P

Page 65: Algorithme et structure de données

Partitionner autour du pivot

int partition(int[] t, int g, int d){ int pivot = t[g], i = g, j = d ; while (i<j) { while(i<=d && t[i]<=pivot) i++; while(t[j]>pivot) j--; if (i<j) echanger(t,i,j); } // j est la position finale du pivot t[g] = t[j]; t[j] = pivot; return j;}

Page 66: Algorithme et structure de données

Tri rapide

La fonction partition() est itérative et sa complexité est en O(n)

Testé sur trois tableaux de taille 1000 dont les éléments sont respectivement, générés aléatoirement, générés par ordre croissant, générés par ordre décroissant, le nombre d'échanges d'éléments observé est respectivement : 5477, 999, et 250 999

On montre que la complexité moyenne du tri rapide est en O(n.log(n))

Mais comme il n'y aucune raison pour que la partition décompose une table de longueur n en deux tables de longueur n/2, la complexité dans le pire des cas est très mauvaise, puisqu'elle est en n2

Page 67: Algorithme et structure de données

Cela existe déjà en Java !

void main(String[] args){

int[] tab={4,3,9,1,0,5,6,3,8,2,0};

afficherTableau(tab);

// triRapide(tab,0,tab.length-1);

java.util.Arrays.sort(tab);

afficherTableau(tab);

}