Les tris - The IC Home Page is in:ic.epfl.ch

publicité
SDA
SDA
Tris
Tris
Introduction à la Programmation Objet :
Objectifs du cours d’aujourd’hui
Continuer l’approfondissement de la programmation de base en
présentant d’autres thèmes de l’informatique :
Structures de données abstraites
Algorithmes de tri
◮
Laboratoire d’Intelligence Artificielle
Faculté I&C
◮
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
introduction aux structures de données abstraites (sda) :
◮
listes chaînées
◮
piles
introduction aux algorithmes de tris
IPO – Cours 12 :– Récursivité | Complexité– – 1 / 54
SDA
Listes
Pourquoi modéliser les données ?
Piles
IPO – Cours 12 :– Récursivité | Complexité– – 2 / 54
SDA
Listes
Une “structure de données abstraite” ?!?
Piles
Tris
Tris
L’élaboration d’un algorithme est grandement facilité par
l’utilisation de structures de données abstraites, de plus haut
niveau, et de fonctions de manipulations associées.
Une structure de données doit modéliser au mieux les
informations à traiter pour en faciliter le traitement par l’algorithme
considéré.
Exemples généraux :
tableau (au sens général du terme)
contenu : divers éléments de types à préciser
interactions : demander la taille du tableau, accéder
(lecture/écriture) à chaque élément
individuellement, ...
Choisir les bons modèles de données est aussi important que le
choix de bons algorithmes
Algorithme et structure de données abstraite sont intimement liés :
Exemple informatique élémentaire :
Programme = algorithme + données
Vous connaissez déjà des structures de données abstraites, très
simples : les types élémentaires.
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 3 / 54
Une structure de données abstraite (S.D.A.) est un ensemble
organisé d’informations (ou données) reliées logiquement et
pouvant être manipulées non seulement individuellement mais
aussi comme un tout.
Par exemple, un int
interactions : affectation, lecture de la valeur, +, -, *, /
IPO – Cours 12 :– Récursivité | Complexité– – 4 / 54
SDA
Listes
Piles
Tris
Spécifications des
structures de données abstraites
SDA
Listes
Tris
Une S.D.A. est caractérisée par :
◮ son contenu
◮
Une structure de données abstraite définit une abstraction des
données et cache les détails de leur implémentation.
les interactions possibles (manipulation, accès, ...)
Par exemple, vous ne pensez pas un int comme une suite de
32 bits, mais bien comme un “entier” (dans un certain intervalle)
avec ses opérations propres : +, -, *, /
Du point de vue informatique, une structure de données abstraite
peut être spécifiée à deux niveaux :
◮
niveau fonctionnel / logique : spécification formelle des
données et des algorithmes de manipulation associés
◮
niveau physique (conception) : comment est implémentée la
structure de données abstraite dans la mémoire de la
machine
Spécifications des S.D.A. [2]
Piles
abstraction : identifier précisément les caractéristiques de l’entité
(par rapport à ses applications), et en décrire les propriétés.
☞ déterminant pour l’efficacité des programmes utilisant ces
données.
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 6 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 5 / 54
SDA
Listes
Spécifications des S.D.A. [3]
Piles
SDA
Listes
Divers exemples de S.D.A.
Piles
Tris
Tris
Une structure de données abstraite modélise donc l’ensemble
des services désirés plutôt que l’organisation intime des données
(détails d’implémentation)
On identifie usuellement quatre types de “services” :
Il existe de nombreuses structures de données abstraites en
informatique.
Dans ce cours, nous n’allons voir que deux parmi les plus
fondamentales :
1. les modificateurs, qui modifient la S.D.A.
2. les sélecteurs, qui permettent “d’interroger” la S.D.A.
◮
◮
3. les itérateurs, qui permettent de parcourir la structure
4. les constructeurs
Exemple :
tableau
modifieur : affectation d’un élément (t[i]=a)
sélecteur : lecture d’un élément (t[i])
sélecteur : le tableau est-il vide ? (t.length == 0)
itérateur : index d’un élément ([i] ci-dessus)
constructeur :(new)
Autres :
◮ files d’attente (avec ou sans priorité)
◮
◮
◮
◮
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 7 / 54
les listes
et les piles
multi-listes
arbres (plein de sorte...)
graphes
tables de hachage
IPO – Cours 12 :– Récursivité | Complexité– – 8 / 54
SDA
Listes
Listes
SDA
Listes
Piles
Listes
Piles
Tris
Tris
Exemple concret :
visionneuse stéréo (essayez d’accéder
Spécification logique :
Ensemble d’éléments successifs (pas d’accès direct), ordonnés
ou non
à la 3e image directement, sans passer par
la 2e !)
Interactions :
◮ Accès au premier élément (sélecteur)
◮
◮
◮
◮
◮
Accès à l’élément suivant d’un élément (sélecteur)
Modifier l’élément courant (modificateur)
Exemple informatique :
Insérer/supprimer un élément après(/avant) l’élément courant
(modificateur)
( a ( b ( c (d))))
Tester si la liste est vide (sélecteur)
Parcourir la liste (itérateur)
a
b
c
d 0
Une liste peut être vue comme une structure récursive :
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 9 / 54
SDA
Listes
Réalisations d’une liste
Tris
J. Sam
liste = vide
Listes
Pourquoi des listes dynamiques ?
Piles
◮
◮
c EPFL 2002–2012
OU
IPO – Cours 12 :– Récursivité | Complexité– – 10 / 54
SDA
Piles
liste = élément + liste
Réalisation statique :
tableau
Réalisation dynamique (liste chaînée) :
class Liste {
Noeud tete; // le debut de la liste
Noeud courant; // l’element sur lequel
//on est positionn’e
...
void inserer(Type donnee) {
...
}
}
class Noeud {
Type donnee;
Noeud suivant;
Noeud(Type donnee) {
this.donnee = donnee;
suivant = null;}
}
IPO – Cours 12 :– Récursivité | Complexité– – 11 / 54
Tris
Les tableaux sont un type de donnée très utile en programmation
mais présentent deux limitations :
1. Les données sont contigües (les unes derrière les autres)
et donc l’insertion d’un nouvel élément au milieu du tableau
demande la recopie (le décalage) de tous les éléments
suivants.
=⇒ insertion en O(n)
2. Pour les tableaux statiques, augmenter la taille (par exemple
si elle n’est pas connue a priori) nécessite la création d’un
nouveau tableau
=⇒ O(n)
c EPFL 2002–2012
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 12 / 54
SDA
Listes
Piles
Tris
Complexité des opérations élémentaires sur
les listes
SDA
Listes
Exemples d’insertion d’un élément
Piles
Tris
◮
Insérer un élément :
O(1)
Supprimer un élément :
O(1)
Après un élément donné (l’élément courant ici) :
void insere(Type donnee)
{
Noeud e = new Noeud(donnee);
e.suivant = (this.courant).suivant;
courant.suivant = e;
}
Calculer la longueur :
O(n)
(voire O(1) si le stockage de cette valeur est effectué,
par exemple en particulier si “longueur” a été spécifiée
dans les “services” de la SDA “liste”)
Vider la liste :
O(n)
Parcourir la liste :
tête
O(n)
2
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
Listes
Exemple de calcul de la longueur
Piles
1
nouveau noeud
donnée
IPO – Cours 12 :– Récursivité | Complexité– – 13 / 54
SDA
courant
IPO – Cours 12 :– Récursivité | Complexité– – 14 / 54
SDA
Listes
Piles
Piles
Tris
Tris
Spécification :
Une pile est une structure de données abstraite dynamique
contenant des éléments homogènes (de type non précisé) à 1
point d’accès et permettant
int taille(Liste liste)
{
int taille=0;
Noeud n=tete;
while (!n.suivant == null) {
taille++;
n = n.suivant;
}
return taille;
}
◮
◮
◮
◮
d’ajouter une valeur à la pile (empiler ou push);
de lire la dernière valeur ajoutée ;
d’enlever la dernière valeur ajoutée (dépiler ou pop);
de tester si la pile est vide.
On ne “connait” donc de la pile que son dernier élément.
Exemple d’implémentation physique : tableau
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 15 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 16 / 54
SDA
Listes
Piles : exemples
SDA
Listes
Piles
Piles : exemples (2)
Piles
Tris
Tris
Exemple d’utilisation (formelle) :
Exemples concrets :
◮
◮
◮
empiler x
x
empiler a
a
x
dépiler
x
empiler b
b
x
empiler y
y
b
x
dépiler
b
x
une pile d’assiettes
poupées russes
une tour dans le jeu des tours de Hanoi
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 17 / 54
SDA
Listes
Exemple d’utilisation des piles
Piles
IPO – Cours 12 :– Récursivité | Complexité– – 18 / 54
SDA
Listes
Tris
Tris
Le problème des parenthèses : étant donnée une expression avec
des parenthèses, est-elle bien ou mal parenthésée ?
((a + b) ∗ c − (d + 4) ∗ (5 + (a + c))) ∗ (c + (d + (e + 5 ∗ g) ∗ f ) ∗ a)
(correct)
(a + b)(
(incorrect)
Encore un peu plus complexe : différentes parenthèses
Exemple avec [ et (
Exemple
Tant que lire caractère c
Si c est ( ou [
empiler c
Sinon
Si c est ) ou ]
c ′ ← lire la pile
Si c et c ′ correspondent
dépiler
Sinon
ÉCHEC
Si pile vide
OK
Sinon
ÉCHEC
([])[()(()[])] ☞ correct
([)] ☞ incorrect
Autres exemples d’utilisation des piles (non traités ici) :
◮
◮
c EPFL 2002–2012
Vérification de parenthésage
Piles
tours de Hanoi
notation postfixée (ou “polonaise inverse”) :
4 2 + 5∗
(☞ 5 ∗ (4 + 2))
J. Sam
Entrée : ([)]
empile (
(
empile [
[
(
lu = ), top = [
→ ne correspond pas
=⇒ ERREUR
c EPFL 2002–2012
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 19 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 20 / 54
SDA
Listes
Deuxième Exemple
SDA
Listes
Piles
Code Java
Piles
Tris
Tris
Entrée : ([]())
empile (
(
empile [
[
(
lu ] → correspond =⇒ dépile
(
empile (
(
(
lu ) → correspond =⇒ dépile
(
lu ) → correspond =⇒ dépile
pile vide =⇒ OK
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
boolean check(String s) {
Pile p;
for (int i=0; i < s.length(); i++) {
if (s.charAt(i) == ’(’) || (s.charAt(i) == ’[’))
empile(p,s[i]);
else if (s.charAt(i) == ’)’) {
if (top(p) == ’(’)
depile(p);
else
return false;
} else if (s.charAt(i) == ’]’) {
if (top(p) == ’[’)
depile(p);
else
return false;
}
}
return est_vide(p);
}
IPO – Cours 12 :– Récursivité | Complexité– – 21 / 54
SDA
Listes
S.D.A en Java
IPO – Cours 12 :– Récursivité | Complexité– – 22 / 54
SDA
Tris
Piles
Tris
Tris
Bien sûr, Java a déjà tout prévu pour vous:
◮
Classes collection du paquetage java.util
◮
◮
Ensembles
Listes
◮
◮
◮
◮
◮
Terminons nos approfondissements en nous intéressant au
problème du tri d’une S.D.A.
vecteurs
piles
listes chaînées
..
Maps
☞ semestre de printemps
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 23 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 24 / 54
SDA
Tris
Algorithmes et données : les tris
SDA
Tris
Les tris
Par exemple : on cherche à trier un tableau d’entiers de taille fixe.
Les méthodes de tris sont très importantes en pratique non
seulement en soi, mais aussi parce qu’elles interviennent dans
beaucoup d’autres algorithmes.
Elles sont par exemple nécessaires pour faire une recherche
efficace.
Le problème du tri est également un problème intéressant en tant
que tel et un bon exemple de problème pour lequel il existe de
nombreux algorithmes.
entrée
6
1
2
3
6
2
programme de tri
Remarques :
◮ un tri ne supprime pas les doublons
Spécification du problème :
On considère une structure de données abstraite contenant des
éléments que l’on peut comparer entre eux : il existe une relation
d’ordre totale sur l’ensemble des éléments
On dira que la S.D.A est triée si ses éléments sont disposés par
ordre croissant pour l’opérateur de comparaison.
◮
quel que soit l’algorithme de tri, une S.D.A. vide ou réduite à
un seul élément est déjà triée !...
On parle de tri interne (par opposition à tri externe) lorsque l’on
peut effectuer le tri en mémoire dans la machine, sans utiliser de
support extérieur (fichier).
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 26 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 25 / 54
SDA
Tris
sortie
1
2
2
3
6
6
Un premier exemple : le tri par insertion
SDA
Tris
Le principe du tri par insertion est extrêmement simple :
1
3
5
2
4
6
un élément mal placé dans le tableau va systématiquement être
inséré à sa “bonne place” dans le tableau.
Tant que il y a un élément mal placé
on cherche sa bonne place
on déplace l’élément à sa bonne place
−→
1
2
3
5
4
6
−→
1
2
3
4
5
6
Tant que il y a un élément mal placé
on cherche sa bonne place
on déplace l’élément à sa bonne place
Par "élément mal placé", on entend ici tout élément du tableau
strictement plus petit que son prédécesseur.
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 27 / 54
Exemple de déroulement du tri par insertion
IPO – Cours 12 :– Récursivité | Complexité– – 28 / 54
SDA
Tris
tri par insertion : résolution globale
SDA
Tris
tri par insertion : résolution détaillée
Le bloc mal placé
Le schéma général de l’algorithme de tri par insertion est donc le
suivant :
entrée : un tableau tab
sortie : indice du 1er élément de tab de prédécesseur
strictement plus grand
tri insertion
entrée : un tableau
sortie : le tableau trié
Par convention, s’il n’y a pas d’élément mal placé, la sortie sera
l’indice du premier élément du tableau (0 en Java).
Tant que il y a un élément mal placé
on cherche sa bonne place
Comme le 1er élément de tab ne peut être mal placé (car sans
prédécesseur), le bloc mal placé parcourira donc les éléments
de tab à partir du 2e.
on déplace l’élément à sa bonne place
Le bloc mal placé effectue donc une itération sur les éléments
de tab, du deuxième au dernier.
☞ Il faut spécifier plus clairement les blocs ci-dessus.
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 30 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 29 / 54
SDA
Tris
tri par insertion : résolution détaillée (2)
SDA
Tris
Le bloc bonne place
tri par insertion : résolution détaillée (3)
Le bloc déplace
entrée : un tableau tab et l’indice pos d’un élément mal
placé
sortie : l’indice newpos de la bonne place de l’élément mal
placé dans le tableau.
entrée : un tableau tab, un indice d’origine pos et un indice
final newpos
Il doit déplacer l’élément d’indice pos dans tab à l’indice newpos.
On peut effectuer cette opération par décalages successifs (en
utilisant un stockage temporaire tmp).
La “bonne position” correspond à la plus grande position newpos
(<pos) dans le tableau tab telle que
tab[newpos-1]≤tab[pos].
tmp
Le bloc bonne place doit donc parcourir les positions de tab,
entre le premier élément et pos, à la recherche d’une bonne
position.
tab
c EPFL 2002–2012
Le bloc bonne place effectue donc aussi une itération sur les
éléments du tableau, du premier élément à celui d’indice pos.
J. Sam
...
newpos newpos+1
pos
c EPFL 2002–2012
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 31 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 32 / 54
SDA
Tris
Tri par insertion : codage
SDA
Tris
tri par insertion : codage (3)
Codage de la fonction bonne place :
Codage de l’algorithme de tri par insertion :
int bonnePlace(int pos, int tab[]) {
// il est important de declarer i avant : pourquoi
int i;
for (i = 0; (i < pos) && (tab[i] <= tab[pos]); i++);
return i;
}
void triInsertion(int tab[], int taille) {
for (int pos=malPlace(tab,taille); pos > 0;
pos = malPlace(tab,taille))
deplace(pos, bonnePlace(pos,tab), tab);
}
Codage de la fonction déplace :
Codage de la fonction mal placé :
void deplace(int pos, int newpos,
int tab[]) {
int tmp = tab[pos]; // stockage temporaire
for (int i=pos; i > newpos; i--) {
tab[i] = tab[i-1]; }
tab[newpos] = tmp;
}
int malPlace(int tab[], int taille) {
for (int i=1; i < taille; i++)
if (tab[i-1] > tab[i])
return i;
return 0;
}
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 33 / 54
SDA
Tris
Version récursive
IPO – Cours 12 :– Récursivité | Complexité– – 34 / 54
SDA
Tris
Version récursive : exemple
On peut aussi concevoir le tri par insertion de façon récursive :
1
tri
entrée : tableau de n éléments
sortie : tableau trié
1
condition arrêt : moins de 2 éléments
tri (instance réduite du problème)
entrée : tableau de n − 1 éléments
sortie : tableau trié
3
3
5
5
2
6
4
2
6
4
5
6
4
tri
1
2
3
...
insertion
insertion du nème élément dans le tableau trié de n − 1 éléments
1
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 35 / 54
2
3
4
5
6
IPO – Cours 12 :– Récursivité | Complexité– – 36 / 54
SDA
Tris
Implémentation récursive
SDA
Tris
Schéma des appels récursifs : exemple
L’algorithme de tri récursif sera implémenté en Java par la
fonction :
// trie le tableau tab entre first et last
void triRecursif(int tab[], int first, int last) {
if (last > first) // moins de 2 elements -> fini
{
triRecursif(tab, first, last-1);
deplace(last, bonnePlace(last, tab), tab);
}
}
triRecursif({3,2,1},0,2)
{1,2,3}
triRecursif({3,2,1},0,1);
deplace(2, 0, {2,3,1})
{2,3,1}
triRecursif({3,2,1},0,0);
Appel de départ :
deplace(1, 0, {3,2,1})
triRecursif(monTab, 0, taille-1);
{3,2,1}
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 37 / 54
SDA
Tris
Schéma des appels récursifs : explications
IPO – Cours 12 :– Récursivité | Complexité– – 38 / 54
SDA
Tris
En rouge, l’élément est trié (ce qui est automatiquement vrai avec
une tableau de taille 1).
En vert, l’élément est celui que l’on va insérer au bon endroit.
L’appel deplace(1,0,{3,2,1}) dit qu’il faut déplacer l’élément de la
position 1 (donc le 2) à la position 0 (donc à la place du 3).
Cela donne donc un sous-tableau (indices 0 et 1) trié: {2, 3, 1}.
L’idée du tri fusion est de :
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 39 / 54
Autre exemple de tri: le tri par fusion
◮
Séparer le tableau initial en deux parties égales,
◮
Trier chaque partie indépendamment de façon récursive,
◮
Fusionner les deux parties triées ainsi obtenues.
IPO – Cours 12 :– Récursivité | Complexité– – 40 / 54
SDA
Tris
Tri par fusion: complexité(1)
SDA
Tris
Tri par fusion: complexité(2)
L’algorithme du tri fusion est alors simple :
la fonction trifusion(t, i, j) suivante effectue le tri fusion
du tableau t entre les indices i et j.
La fusion de deux tableaux triés t1 et t2 (de taille respective n1 et
n2 ) ne requiert donc qu’un seul parcours, en parallèle, des deux
tableaux en entrée. Complexité linéaire: O(max(n1 , n2 ))
trifusion(t, i, j)
Si (i== j)
retourne le tableau t[i];
Sinon
milieu=(i + j)/ 2;
t1 = trifusion(t, i, milieu);
t2 = trifusion(t, milieu + 1,j);
retourner fusion(t1 , milieu- i + 1,t2 , j - milieu);
fusion(t1 , n1 , t2 , n2 )
créer un nouveau tableau t;
i = 0; j = 0;
Tant que (i ≤ n1 et j ≤ n2 )
Si (t1 [i] < t2 [j])
ajouter t1 [i] à t; i++;
Sinon
ajouter t2 [j] à t; j++;
Tant que (i ≤ n1 )
ajouter t1 [i] à t; i++;
Tant que (j ≤ n2 )
ajouter t2 [j] à t; j++;
retourner t;
Dans cet algorithme, la fusion de deux tableaux (de complexité
O(n)) sera appelée autant de fois que le tableau initial de taille n
peut être récursivement coupé en deux, soit log2(n) fois. La
complexité de l’algorithme est donc en O(nlog(n)).
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 41 / 54
SDA
Tris
...encore un autre tri: le tri rapide (Quicksort)
IPO – Cours 12 :– Récursivité | Complexité– – 42 / 54
SDA
Tris
Quicksort(1)
Pour un tableau A de N éléments, la recherche de l’élément pivot
fonctionne de la façon suivante :
Un autre algorithme de tri, fondé sur le paradigme Diviser pour
régner et appelé quicksort a été proposé en 1962, par C. A. R.
Hoare,
Cet algorithme:
◮ Permet de placer un élément à sa place (le pivot)
◮
◮
Ramène ainsi le problème au tri des 2 morceaux de tableau
entourant cet élément
La séparation du tableau ne se fait donc pas en deux parties
égales, mais en deux parties qui entourent un élément bien
placé.
◮
Initialisation : i = 2, j = N
◮
Rechercher, en augmentant i, le premier élément supérieur à
A1 (il marque la limite des nombres inférieurs à A1 ) et, en
diminuant j, le premier élément inférieur à A1 (qu’il faudra
placer dans le morceau de tableau des nombres inférieurs à
A1 ).
◮
Si i < j, échanger Ai et Aj continuer des traitements
identiques jusqu’au moment où i ≥ j on termine par l’échange
éventuel de Aj et A1 .
On relance l’algorithme récursivement pour trier les deux parties
du tableau de part et d’autre de l’élément pivot.
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 43 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 44 / 54
SDA
Tris
Quicksort(2)
SDA
Tris
Quicksort(3)
Prenons par exemple le tableau A suivant à trier :
7
8
9
1
0
2
5
On continue à chercher, en nous déplaçant vers la droite, le
premier élément supérieur à A1 mais à partir de A3 . Il s’agit de A3
qui vaut 9. De même, cherchons à partir de A7 et en nous
déplaçant vers la gauche, le premier élément inférieur à A1 . Il
s’agit de A7 qui vaut 5.
6
Recherchons, à partir de A2 , en nous déplaçant vers la droite, le
premier élément supérieur à A1 . Il s’agit de A2 qui vaut 8 (en
rouge). De même, cherchons à partir de A8 et en nous déplaçant
vers la gauche, le premier élément inférieur à A1 . Il s agit de A8
qui vaut 6 (en magenta).
7
8
9
1
0
2
5
6
6
9
1
0
2
5
6
9
1
0
2
5
8
7
6
5
1
0
2
9
8
On les échange:
On les échange
7
7
8
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 45 / 54
SDA
Tris
Quicksort(3)
IPO – Cours 12 :– Récursivité | Complexité– – 46 / 54
SDA
Tris
7
6
5
1
0
2
9
8
On continue à chercher, en nous déplaçant vers la droite, le
premier élément supérieur à A1 mais à partir de A4 . Il s agit de A7
qui vaut 9 (i vaut donc 7). De même, cherchons à partir de A6 et
en nous déplaçant vers la gauche, le premier élément inférieur à
A1 . Il s’agit de A6 qui vaut 2 (j vaut donc 6).
7
6
5
1
0
2
9
Quicksort(4)
L’élément en position 6 constitue l’élément pivot.
2
6
5
1
0
7
9
8
Il faut alors trier récursivement les morceaux de tableau dont les
indices vont de 1 à 5 et de 7 à 8:
8
2
6
5
1
0
7
9
8
Comme i > j, il n y a pas d’échange mais par contre, on échange
A1 et Aj .
2
c EPFL 2002–2012
J. Sam
6
5
1
0
7
9
8
Et l’élément en position 6 est à sa place définitive. Il constitue
l’élément pivot .
IPO – Cours 12 :– Récursivité | Complexité– – 47 / 54
c EPFL 2002–2012
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 48 / 54
SDA
Tris
L’algorithme Quicksort(tableau, inf, sup)
SDA
Tris
Si inf ≤ sup
i = inf + 1; j = sup;
Tant que i < j
Tant que (A[i] < A[inf ] et i < sup)
i++:
Tant que (A[j] > A[inf ] et j > inf )
j- -;
Si (i < j)
swap(A[ i], A[ j]);
Si (A[j] < A[inf ])
swap(A[j], A[inf ]);
i++; j- -;
Si (j − 1 > inf )
quicksort(tableau, inf, j - 1);
Si (j + 1 < sup)
quicksort(tableau, j + 1, sup);
On peut montrer que la complexité du quicksort:
◮
◮
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
Tris
Conclusions sur les tris
SDA
Tris
◮
◮
◮
◮
◮
◮
Est en moyenne en O(nlog(n)) . En pratique, la complexité
moyenne du quicksort est même meilleure que la complexité
du tri-fusion (car le facteur multiplicatif de nlog(n) est plus
petit).
Conclusions sur les tris : comparaison
COMPLEXITÉ TEMPORELLE
moyenne pire cas
bulles
O(n2 )
O(n2 )
2
par sélection
O(n )
O(n2 )
2
insertion
O(n )
O(n2 )
de Shell
–
O(n1.5 )
quick sort
O(n log n) O(n2 )
par tas
O(n log n) O(n log n)
fusion
O(n log n) O(n log n)
optimum théorique O(n log n) O(n log n)
Ce n’était qu’une brève introduction, du fait de l’importance des
tris.
Il existe beaucoup d’autres algorithmes de tris :
◮
Est au pire en O(n2 )
IPO – Cours 12 :– Récursivité | Complexité– – 50 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 49 / 54
SDA
Complexité de Quicksort
par sélection
bulles
tri shaker
tri de Shell
tri tournois
tri par tas
...
Mais en pratique : à partir de quelle taille les méthodes simples
deviennent-elle vraiement plus mauvaises que les méthodes
sophistiquées (quick sort ou tri par tas) ?
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 51 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 52 / 54
SDA
Tris
Conclusions sur les tris : comparaison (2)
SDA
Tris
Cela dépend de nombreux facteurs, mais en général on peut dire
que pour moins d’une centaine d’éléments les tris sophisitiqués
n’en valent pas la peine.
Ce que j’ai appris aujourd’hui
◮
Expérimentalement le quick sort est 2 a 3 fois plus rapide que le
tris par tas
◮
Dans le cas de liste presque triées, les tris par insertion sont
efficaces.
◮
les bases de la formalisation des données : les structures
de données abstraites
les deux structures de données abstraites les plus utilisées
en informatique (en plus des tableaux et des types
élémentaires) : les listes chaînées et les piles
introduction aux algorithmes de tri
Le tri bulles, très simple à écrire, est le moins bon des tris : à
proscrire (sauf à des fins pédagogiques).
c EPFL 2002–2012
c EPFL 2002–2012
J. Sam
J. Sam
IPO – Cours 12 :– Récursivité | Complexité– – 53 / 54
IPO – Cours 12 :– Récursivité | Complexité– – 54 / 54
Téléchargement