Tri rapide - TSI Ljf.html

publicité
Informatique
TD/ TP 4.2
Tri rapide (quick sort)
On se propose ici d’implémenter l’algorithme de tri rapide ("quick sort") étudié en cours.
1 Partitionnement d’un tableau suivant un pivot
1) Dérouler étape par étape l’algorithme de partitionnement en place de t = [8; 4; 2; 15; 17; 23; 0; 1]
avec le pivot t[0] = 8 en complétant les tableaux suivants.
itération intialisation
1
2
k
1
2
t[k]
4
4
m
0
1
2
t
[8; 4; 2; 15; 17; 23; 0; 1]
[8; 4; 2; 15; 17; 23; 0; 1]
[8; 4; 2; 15; 17; 23; 0; 1]
itération
k
t[k]
m
t
3
4
5
3
8
3
4
15
3
[8; 4; 2; 15; 17; 23; 0; 1]
5
23
3
[8; 4; 2; 15; 17; 23; 0; 1]
itération
k
t[k]
m
t
6
7
7
1
5
[8; 4; 2; 0; 1; 23; 15; 17]
post traitement
[8; 4; 2; 15; 17; 23; 0; 1]
6
0
4
[8; 4; 2; 0; 17; 23; 15; 1]
[1; 4; 2; 0; 8; 23; 15; 17]
2) Expliquer en quoi consiste le post traitement qui succède aux itérations ?
On met en place le pivot 8 à sa place définitive.
3) Ecrire une fonction echange qui prend en argument un tableau t, deux entiers i et j et échange les
éléments t[i] et t[j].
def echange(t,i,j):
x=t[i]
t[i]=t[j]
t[j]=x
4)
Ecrire une fonction segmenter qui prend en argument un tableau t, les indices de début i et de fin
j de partition t :
qui partitionne ses éléments en prenant pour pivot l’élément de gauche t[i],
qui renvoie la position finale du pivot (on utilisera en boîte noire la fonction echange
précédemment écrite).
def segmenter(T,i,j):
p = T[i] # p : pivot du segment = 1er élément de la liste à fractionner
m = i # m : indice de séparation entre G1 (valeurs ≤ p) et G2 (valeurs>p)
for k in range(i+1,j):
if T[k]<=p:
m=m+1
echange(T,m,k)
echange(T,i,m)
return m
Lycée Jules Ferry Cannes
Page 1 sur 2
TSI2
Informatique
TD/ TP 4.2
Tri rapide (quick sort)
2 Tri rapide récursif
5) Dérouler étape par étape l’algorithme de tri rapide du tableau t = [8; 4; 2; 15; 17; 23; 0; 1]
(attention ce tableau après appel de la fonction tr a la forme obtenue en fin de traitement de la
question 1). On complètera pour cela l'arbre des appels récursifs (tr est la fonction récursive de tri
rapide; le respect de l'ordre des valeurs dans les partitions est impératif dans la liste d'entrée de
tr) ainsi que le pivot obtenu à chaque appel.
tr([2,0])
2
tr([1,4,2,0])
8
tr([23,15,17])
0
tr([4])
1
tr(t)
tr([0])
4
tr([17,15])
tr([15])
15
17
23
6) Ecrire une fonction récursive tri_rapide_rec qui prend en argument un tableau t, deux entiers i et
j, et qui réalise un tri rapide du sous-tableau t[i : j].
def tri_rapide_rec(M,i,j):
T=M[:]
if i<j:
k = segmenter(T,i,j)
tri_rapide_rec(T,i,k-1)
tri_rapide_rec(T,k+1,j)
return T
7) Ecrire enfin la fonction tri_rapide qui prend en argument un tableau t et réalise un tri rapide de t
(on utilisera la fonction tri_rapide_rec).
def tri_rapide(T):
return tri_rapide_rec(T,0,len(T))
3 Améliorations et performances temporelles
8)
-
Améliorer la fonction segmenter afin de :
choisir aléatoirement le pivot (on pourra importer le paquet random et utiliser la commande
random.randint(a,b), qui choisit aléatoirement un entier dans [a; b]),
ramèner le pivot en début de partition pour que la suite de l'algorithme convienne,
trier le tableau et renvoyer la position finale du pivot (comme cela était déjà le cas).
def segmenter(T,i,j):
pa = randint(i,j-1)
echange(T,pa,i)
9) Afin d'évaluer l'effet de cette modification d'algorithme avec une liste triée de 980 éléments (soit
presque triée) sur la durée d'exécution, on pourra importer le module time du paquet time.
La fonction time() ainsi importée renvoie le temps en seconde.
En faisant la différence entre le temps après l'exécution et celui avant l'exécution, on peut
déterminer le temps mis par l'algorithme en seconde.
10) On pourra aussi comparer avec les temps nécessaires au tri par insertion.
Ressources : Damien BROIZAT (TSI2 Cannes)
Lycée Jules Ferry Cannes
Page 2 sur 2
TSI2
Téléchargement