L2S3 Harmonisation Algorithmique 2015–2016
UFR d’IEEA – Université Lille 1
TP : Tri Rapide
Dans ce TP vous pouvez utiliser les fonctions données dans le fichier permutation.py
disponible sur le portail.
1 Principe
Le tri rapide, ou quicksort, est fondé comme le tri par fusion sur le paradigme "diviser
pour régner". C’est en effet également un algorithme récursif qui procède en divisant le
tableau en deux sous-tableaux, les tri (récursivement) et recombine les deux parties.
La différence entre ces deux algorithmes de tri réside dans la manière de diviser le
tableau puis de recombiner. Contrairement au tri par fusion, l’étape la plus coûteuse du
tri rapide, donc celle où s’effectue tout le travail, est la division en deux sous tableaux.
La recombinaison et immédiate et ne nécessite aucun travail.
De plus le tri rapide est un tri "en place" ou "sur place" : un espace mémoire constant
en plus du tableau à trier est suffisant pour effectuer ce tri.
De manière plus détaillée le principe du tri rapide est le suivant :
1. Diviser/Partitionner : Un élément du tableau est choisi arbitrairement, on appel
cet élément le pivot. La division consiste à placer tous les éléments de valeur infé-
rieure à celle du pivot au début du tableau et tous les supérieurs en fin de tableau.
Les éléments de valeur égale au pivot se trouvent au milieu. Le tableau est donc
divisé en trois parties : les éléments inférieurs, égaux puis supérieurs au pivot.
2. Trier : Il s’agit simplement de trier récursivement les deux parties contenant les
éléments inférieurs et supérieurs au pivot.
3. Recombiner : Rien à faire, le tableau est déjà trié !
2 Choix du pivot
Comme vous le verrez dans la suite du TP choisir une bonne valeur de pivot est très
important pour avoir la meilleur complexité possible. Cependant choisir le pivot optimal
à chaque appel récursif nécessite presque autant d’opérations que pour trier le tableau,
c’est pourquoi on choisit en général une valeur aléatoirement dans le tableau.
Q1 . Ecrivez la fonction pivot retournant une valeur ( pas un indice !) choisie aléatoi-
rement dans le tableau tentre les indices det f, où t,det fsont donnés en paramètre.
3 Partition
Il y a plusieurs méthodes pour écrire un algorithme itératif de partition, l’une d’elles
consiste à maintenir quatre zones délimitées par trois indices, a,bet c, comme illustré sur
la Figure 1 :
1. les éléments inférieurs au pivot se trouvent aux indices strictement inférieurs à a,
1
2. les éléments égaux au pivot se trouvent entre les indices aet c1,
3. les éléments supérieurs au pivot sont aux indices strictement supérieurs à b,
4. les éléments restants entre les indices cet bn’ont pas encore été comparés au pivot
et n’ont donc pas encore été placés dans l’une des trois précédentes parties.
a b
< pivot > pivot
c
= pivot ???
Figure 1 – Partition
L’idée est de comparer l’élément d’indice cau pivot puis de l’insérer dans l’une des
trois parties, inférieur, supérieur ou égale au pivot, suivant sa valeur.
3.1 La fonction partition
Q2 . Donnez les conditions vérifiées par les indices a,bet clorsque la partition est
terminée, c’est-à-dire lorsqu’il ne reste plus d’éléments qui n’ont pas été comparés au
pivot.
Q3 . Quel est, en fonction (éventuellement) de a,bet c, le plus grand indice xd’un
élément strictement inférieur au pivot à la fin de l’algorithme de partition ?
Q4 . Quel est, en fonction (éventuellement) de a,bet c, le plus petit indice yd’un élément
strictement supérieur au pivot à la fin de l’algorithme de partition ?
Q5 . Donnez les valeurs initiales des indices a,bet cen fonction des indices det fde
début et fin de tableau, c’est-à-dire lorsqu’aucun élément n’a encore été comparé au pivot.
Q6 . Ecrivez la fonction partition qui partitionne selon valeur pdu pivot les éléments
du tableau tcompris entre les indices det fen trois parties : éléments inférieurs, égaux et
supérieurs au pivot. Cette fonction prend en paramètre t,d,fet pet retourne le couple
(x,y) d’indices où xest le plus grand indice d’un élément strictement inférieur au pivot
et yest le plus petit indice d’un élément supérieur au pivot à la fin de l’algorithme de
paritionnement.
Q7 . Quelle propriété intéressante pour des éléments au cours d’un algorithme de tri est
vérifiée par tous les éléments de valeur égale au pivot lorsque la partition est terminée ?
3.2 Complexité
Q8 . L’algorithme a-t-il des cas pire ou meilleur que les autres en terme de nombre de
comparaisons effectuées entre le pivot et les autres éléments du tableau ? Si oui donnez
ces cas, sinon expliquez pourquoi.
Q9 . Combien de comparaisons entre le pivot et les autres éléments du tableau tentre
les indices det fsont effectuées ? Vous pouvez justifier votre réponse par un argument
(convaincant) ou un calcul.
2
Q10 . Donnez l’ordre de grandeur asymptotique du nombre de comparaisons.
4 Tri récursif
Toute la difficulté du tri se trouve dans la partition du tableau et comme pour le
tri par fusion, une fois la partie délicate de l’algorithme encapsulée dans une fonction
(partition ici) l’algorithme récursif de tri ne prend plus que quelque lignes à écrire.
4.1 La procédure tri_rapide
Q11 . Ecrivez la procédure tri_rapide prenant en paramètre un tableau tet deux
indices det fde début et fin de tableau et qui effectue un tri rapide sur t. Vous pouvez
naturellement utiliser les fonctions pivot et partition écrites précédemment.
Q12 . Justifiez rapidement que l’algorithme effectue bien un tri du tableau. Vous pouvez
pour cela utiliser la propriété vérifiée par les éléments égaux à la valeur du pivot à la fin
de la fonction partition.
4.2 Complexité
Q13 . Donnez l’équation de récurrence décrivant le nombre de comparaisons entre élé-
ments du tableau effectuées lors de l’exécution de la procédure tri_rapide sur un tableau
de taille n. Dans un premier temps on pourra considérer qu’il y a nIéléments inférieurs
et nSéléments supérieurs au pivot.
De plus, dans la suite on supposera qu’une valeur n’apparaît qu’une seule fois dans le
tableau et donc qu’il ne peut pas y avoir plusieurs cases contenant une valeur égale au
pivot.
Q14 . Que devient l’équation de récurrence s’il y a toujours autant d’éléments inférieurs
que d’éléments supérieurs au pivot ?
Q15 . Résoudre l’équation dans ce cas là et donner un ordre de grandeur asymptotique
du nombre de comparaisons que le tri effectue.
Q16 . Que devient l’équation de récurrence si le pivot est toujours l’élément maximum
ou minimum du tableau ?
Q17 . Résoudre l’équation dans ce cas là et donner un ordre de grandeur asymptotique
du nombre de comparaisons que le tri effectue.
Q18 . Déduire de vos résultats précédents un pire et un meilleur cas pour l’algorithme
du tri rapide.
Q19 . Le tri rapide est il intéressant pour un tableau presque trié ? Justifiez votre réponse.
Remarque : La complexité en moyenne du tri rapide, c’est-à-dire la moyenne du
nombre d’opérations sur toutes les données possibles de taille n(= tous les tableau
possibles de taille n), est en Θ(nlog n). En pratique ce tri est généralement plus efficace
que le tri par fusion dont la complexité est toujours en Θ(nlog n).
3
4.3 Preuve de correction
Prouver qu’un algorithme est correct consiste simplement à montrer que le calcul ou
le traitement qu’il effectue est bien celui pour lequel il a été écrit : à partir de données
vérifiant ses conditions d’utilisation il conduira toujours à un état final ou résultat qui
vérifie une propriété attendue.
Une preuve de correction est partielle si elle montre seulement que si l’algorithme
s’arrête alors il est correct. Il faut dans ce cas si possible la compléter par une preuve de
terminaison, c’est-à-dire montrer que l’algorithme va effectivement s’arrêter.
La logique de Hoare permet à partir d’une propriété vraie en début d’algorithme,
comme une condition d’utilisation, de déduire des propriétés vérifiées à chaque étape,
c’est-à-dire entre chaque calculs élémentaires, puis en fin de l’algorithme. Ecrire une preuve
compléte à la main est en général fastidieux.
Cependant la mise en évidence d’invariant de boucle permet souvent de se convaincre
qu’un algorithme itératif est correct. Un invariant de boucle est une propriété qui est
vérifiée après la phase d’initialisation, reste vraie à l’issue de chaque itération et qui
conjointement avec la condition d’arrêt de la boucle permet de montrer que le résultat
obtenu à la fin de la boucle est bien celui qui est attendu.
Q20 . Proposez un invariant (de boucle) pour (l’unique boucle de) l’algorithme de parti-
tionnement.
Q21 . Votre invariant est-il vrai au début de la première itération ?
Q22 . Expliquer pourquoi si l’invariant est vérifié en début d’une itération il sera toujours
vrai au début de l’itération suivante.
Q23 . Donnez une preuve de correction informelle et partielle de l’algorithme.
Q24 . En observant ce qu’il se passe à chaque itération, justifiez que l’algorithme de
partionnement va bien se terminer.
4
1 / 4 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !