MP1 Lycée Janson de Sailly Algorithmes de tri
Algorithmes de tri
Table des matières
1 Tri par insertion 1
2 Tri fusion 2
2.1 Principe.......................... 2
2.2 Algorithme de fusion . . . . . . . . . . . . . . . . . . . 2
2.3 Algorithme du tri par fusion . . . . . . . . . . . . . . . 4
3 Tri rapide (quick sort) 5
3.1 Algorithme du pivot . . . . . . . . . . . . . . . . . . . 5
3.2 Algorithme de tri rapide . . . . . . . . . . . . . . . . . 6
4 Application : recherche de la médiane dans une liste 7
But : étudier trois algorithmes qui permettent de trier les différents
éléments d’un tableau.
On note A[0 ...n1] un tableau contenant néléments qui peuvent
être des entiers, des réels ou, plus généralement, toute collection de
valeurs sur lesquelles on peut définir une relation d’ordre total. En
pratique nous allons étudier des tableaux d’entiers positifs.
On peut accéder à chaque élément du tableau au moyen de son
indice : entier i[[0...n - 1]]. A[i] désigne le (i + 1)ème élément du
tableau. A[0] est le premier élément du tableau et A[n1] le dernier.
La convention adoptée pour les indices est celle que Python utilise
pour les listes ou les tableaux numpy.
1 Tri par insertion
Cet algorithme s’inspire du tri que fait un joueur de cartes lors de
la distribution du jeu. Les cartes qu’il a en main sont déjà triées, la
plus petite étant à gauche et la plus grande à droite. Lorsqu’on lui
distribue une nouvelle carte, il va l’insérer à sa place en la comparant
aux plus grandes valeurs de son jeu.
Supposons que la prochaine "carte" à insérer à la bonne place soit
A[i]. On suppose que le sous-tableau A[0 ...i1] est déjà trié.
L’idée est de créer un trou à l’emplacement où se trouve A[i]
en la sauvegardant temporairement dans une variable temp.
On compare A[i1] et A[i]. Si A[i1]6A[i] c’est terminé
et on remet temp à sa place. Si A[i1]>A[i] on décale
le contenu A[i1] dans la case libre A[i], ce qui déplace le
trou vers la gauche du tableau. On recommence en comparant
A[i2] avec A[i]. Le processus s’arrête lorsque on a trouvé k
tel que A[ik]6A[i] ou si on atteint A[0].
On recommence tout le processus avec la nouvelle carte à insé-
rer, c’est à dire A[i+ 1].
1
MP1 Lycée Janson de Sailly Algorithmes de tri
Précondition :n> 1 # Au moins 2 éléments dans le tableau
fonction TRI_INSERTION(A, n) :
1. pour iallant de 1 à n1faire :
2. temp = A[i]
3. j=i#jest l’indice du trou dans le tableau
4. tant que {j> 0 et A[j1] > temp } faire :
5. A[j] = A[j1]
6. j=j1
7. A[j] = temp
Intérêt : Le tri se fait sur place c’est à dire à l’intérieur même du
tableau. Pas besoin de réserver un espace mémoire supplémentaire.
Réalisation
1. Écrire cet algorithme en langage Python et le tester avec la liste
proposée sur le site mp1.
2. En vous aidant du tableau ci-dessous, calculer la complexité
temporelle de cette fonction dans le meilleur des cas, puis dans
le pire des cas (à définir).
fonction TRI_INSERTION(A, n) Coût Nbre de fois
1pour iallant de 1àn-1 :c1
2 temp = A[i] c2
3 j = i c3
4tant que ( j > 0 et A[j - 1] > temp ) : c4
5 A[j] =A[j - 1] c5
6 j = j - 1 c6
7 A[j] = temp c7
2 Tri fusion
2.1 Principe
Le tri fusion est un exemple du paradigme diviser pour résoudre.
Cela consiste à prendre un problème et à le diviser en deux sous - pro-
blèmes plus simples à résoudre. On utilise ensuite les deux solutions
pour résoudre le problème initial
Prenons l’exemple d’un jeu de 32 cartes à trier. L’idée est de par-
tager ce jeu en deux jeux de 16 cartes (diviser) et de trier séparément
ces deux jeux (résoudre). On ré-assemble ensuite chacun des deux
jeux, grâce à un algorithme de fusion.
2.2 Algorithme de fusion
L’algorithme le plus important de ce tri est celui qui permet la
fusion de deux jeux de cartes triés séparément pour n’en former qu’un
dans lequel toutes les cartes sont triées.
Dans notre cas, les deux jeux de cartes sont en fait un sous-tableau
A[p...q, q + 1, ...r] de A, où p6q < r. Le premier jeux de carte est
représenté par A[p...q] et le second jeu par A[q+ 1, ..., r]. Chacun est
déjà trié séparément, la plus petite valeur étant celle d’indice le plus
bas et la plus grande valeur celle d’indice le plus élevé. On aura donc :
A[p]6A[p+ 1] 6... 6A[q]et A[q+ 1] 6... 6A[r]
L’algorithme de fusion est écrit dans une fonction FUSION qui
prend en argument le tableau A et les trois entiers p,qet r:
On commence par "vider" A[p...r] dans deux sous-tableau : G
pour tous les éléments allant de A[p] à A[q] et Dpour tous les
éléments allant de A[q+1] à A[r].
On remplit ensuite à nouveau A[p...r] en comparant chaque élé-
ment de Get de Dafin de le placer à la bonne place dans
A.
2
MP1 Lycée Janson de Sailly Algorithmes de tri
fonction FUSION(A, p,q,r) :
Variables locales : tableaux d’entiers G[0...qp+ 1] , D[0...rq]
1pour iallant de 0 à qpfaire :
2 G[i] = A[p+i]
3pour jallant de 0 à rq1faire :
4 D[j] = A[q+j+ 1]
5 G[qp+ 1] =
6 D[rq] =
7i= 0
8j= 0
9pour kallant de pàrfaire :
10 si G[i]6D[j]faire :
11 A[k] = G[i]
12 i=i+ 1
13 sinon :
14 A[k] = D[j]
15 j=j+ 1
Aux lignes 5 et 6, on a recours à une astuce qui consiste à placer
une valeur appelée à la fin des tableaux G et D : en pratique, c’est
une valeur strictement supérieure à toutes les valeurs du tableau A
qui fait office de "butée" ou encore de sentinelle. Cela évite d’avoir à
introduire un test au sein de la boucle "pour" destiné à savoir quand
on atteint la fin d’un de ces deux tableaux.
Les lignes 7, 8 et 9 introduisent 3 entiers i,jet kqui sont les
indices des tableaux G,Det A. Pour chaque valeur de kentre pet
q, on compare G[i] et D[j] et on place la plus petite des deux valeurs
dans A[k].
On augmente ensuite iou jsuivant la valeur qui a été transférée.
Le processus est réitéré pour toutes les valeurs de kvariant de pàr,
grâce à la boucle pour, ligne 9.
Réalisation :
1. Écrire la fonction FUSION en Python
2. À l’aide du tableau ci-dessous, montrer que sa complexité tem-
porelle T(n), avec n=rp+ 1 (nombre d’éléments du sous
tableau A[p...r] est O(n).
fonction FUSION(A, p, q, r) : Coût Nbre de fois
1pour iallant de 0àqp:c1
2 G[i] = A[p+i] c2
3pour jallant de 0àrq:c3
4 D[j] = A[q+j+ 1] c4
5 G[qp+ 1] = infini c5
6 D[rq] = infini c6
7i= 0 c7
8j= 0 c8
9pour kallant de pàr:c9
10 si G[i]6D[j]:c10
11 A[k] = G[i] c11
12 i=i+ 1 c12
13 sinon : 0
14 A[k] = D[j] c14
15 j=j+ 1 c15
3
MP1 Lycée Janson de Sailly Algorithmes de tri
2.3 Algorithme du tri par fusion
Soit à trier le sous-tableau A[p...r] (p6r) extrait de A[0...n 1].
La fonction TRI_FUSION, prend en paramètres le tableau A et les
deux entiers pet r. Elle utilise le paradigme "diviser pour résoudre",
c’est à dire qu’elle va séparer A[p...q] en deux tableaux de tailles à
peu près identique qu’elle va trier séparément, avec une approche
purement récursive.
fonction TRI_FUSION(A, p,r) :
1. si p<rfaire :
2. q= Ep+r
2
3. TRI_FUSION(A, p,q)
4. TRI_FUSION(A, q+ 1, r)
5. FUSION(A, p, q, r)
La ligne 1 teste si p<r. Dans le cas contraire, on a soit une
absurdité (r < p), soit il n’y a rien à trier (p== r) puisque le sous-
tableau ne renferme alors qu’un seul élément.
À la ligne 2, on définit l’entier q= Ep+q
2(partie entière) ce
qui permet de diviser A[p...r] en deux sous tableaux de tailles égales
ou environ égales : A[p..q] et A[q+ 1...r] : diviser.
La fonction s’appelle ensuite de façon récursive lignes 3 et 4 pour
trier les deux sous-tableaux obtenus : résoudre.
À la ligne 5, on ré-assemble enfin les deux sous-tableaux triés grâce
à la fonction FUSION étudiée à la section précédente.
Le tri du tableau entier se fait en appelant la fonction
TRI_FUSION(A, 0, n1).
Réalisation :
1. Écrire cette fonction en Python et la tester sur la liste fournie
sur le site mp1.
2. Dessiner l’arbre des appels récursifs de la fonction TRI_FUSION
pour A = [7, 3, 1, 8, 4].
3. En vous aidant du tableau ci-dessous et en supposant que n=
rp+ 1 est toujours divisible par 2 (hypothèse simplificatrice
mais efficace), montrer que sa complexité temporelle T(n)vérifie
l’équation (approchée) :
T(n)=2Tn
2+O(n)
4. En posant n= 2pet en étudiant la suite up=T(2p)
2p, résoudre
cette équation de récurrence et montrer que T(n)= O(nlg(n)
) où lg est le logarithme en base 2.
fonction TRI_FUSION(A, p, r) :Coût Nbre de fois
1si p < r :c1
2 q = E( (p + r)/2 ) c2
3 TRI_FUSION(A, p, q)
4 TRI_FUSION(A, q + 1, r)
5 FUSION(A, p, q, r)
4
MP1 Lycée Janson de Sailly Algorithmes de tri
3 Tri rapide (quick sort)
Le tri rapide est très souvent utilisé, bien que ce ne soit pas le
meilleur en terme de complexité temporelle. Comme le tri par fusion,
il fonctionne lui aussi sur le principe diviser pour résoudre et sur
l’approche purement récursive. En voici le principe :
On commence par choisir une valeur particulière du tableau
qu’on appelle le pivot. On ré-ordonne ensuite le tableau en
plaçant toutes les valeurs < pivot à gauche de celui-ci et toutes
les valeurs > pivot à droite de celui-ci. L’algorithme PIVOT
se charge de faire cela.
À la fin de l’algorithme précédent, le pivot est à la bonne place
dans le tableau. Soit ind_p son indice.
Le tableau A est ensuite divisé en deux sous-tableaux
A[0...ind_p 1] et A[ind_p + 1...n1] à qui on va appliquer
séparément l’algorithme PIVOT : on recommence le premier
point avec chacun des deux sous-tableaux, selon une approche
récursive.
3.1 Algorithme du pivot
Prenons un tableau A[0...n1] contenant n> 1 éléments entiers
positifs que l’on souhaite trier. Pour des raisons qui vont apparaître
plus tard, on va commencer par s’intéresser au sous-tableau A[p...q]
délimité par les indices pet q, vérifiant :
06p<q6n1
On choisit comme pivot de ce sous tableau A[p...q] son dernier
élément A[q].
La fonction PIVOT ci-dessous permet de réordonner les éléments
A[p], A[p+ 1], ..., A[q]en plaçant toutes les valeurs inférieures au
pivot à gauche de celui-ci et toutes les valeurs supérieures au pivot
à droite. Elle retourne l’indice ind_p du pivot, après que A[p...q] ait
été ré-ordonné.
fonction PIVOT(A, p,q) :
1si p<q:
2 pivot = A[q]
3 temp = A[p]
4 min = p
5 max = q
6tant que min < max :
7si temp > pivot :
8 A[max] = temp
9 max = max - 1
10 temp = A[max]
11 sinon :
12 A[min] = temp
13 min = min + 1
14 temp = A[min]
15 A[min] = pivot
16 retourner min
17 sinon :
18 retourner 1
À la ligne 1, on place une condition p<qpour lancer l’algorithme.
En effet, si p > q, c’est absurde et si p== q, A ne contient qu’un
seul élément et il n’est pas nécessaire de le réordonner. Dans ce cas
l’indice retourné vaut 1: cette valeur ne pouvant pas être celle d’un
indice, cela permet de placer une sentinelle dans le programme.
Ligne 2, le pivot choisi est toujours A[q], valeur de plus haut in-
dice et on crée un trou dans A en sauvegardant cette valeur dans la
5
1 / 7 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 !