Version interactive avec LaTeX compilé
Les candidats indiqueront en tête de leur copie le langage de programmation choisi (Pascal ou Caml). Les candidats ayant choisi Caml devront donner le type de chaque fonction écrite, lorsque celui-ci n'est pas imposé. Les candidats travaillant en Pascal pourront écrire des fonctions ou des procédures.
Choix du pivot dans le tri rapide
L'objet de ce problème est le choix d'un pivot dans l'algorithme du tri rapide. On s'intéresse au tri en ordre croissant d'un tableau d'entiers qui pourront toujours être supposés distincts.
En Pascal, on dispose du type tableau suivant :
En Pascal, on dispose du type tableau suivant :
const long_tab = 1000;
type tableau = array[0..long_tab-1] of integer;
La longueur
des tableaux avec lesquels on travaille devra donc être majorée par long_tab et les données sont alors présentes dans la zone indexée par
. Cette longueur utile
devra donc être éventuellement donnée en paramètre.
En Caml, on rappelle que la longueur d'un tableau est donnée par vect_length en Caml light et Array.length en Ocaml.
En Caml, on rappelle que la longueur d'un tableau est donnée par vect_length en Caml light et Array.length en Ocaml.
I Tri rapide d'un tableau
echange : int -> int -> int vect -> unit = <fun>
procedure echange(i, j : integer ; var
I.
Par exemple, le tableau
Un des intérêts importants de cet algorithme est qu'il peut être réalisé en place : le tableau ne sera jamais recopié. Pour cela, les appels récursifs prendront comme arguments les indices délimitant la partie à trier.
I.C.1) Expliquer comment on peut réaliser en place la phase de séparation du tableau en temps
I.C.2) Écrire une fonction separation prenant en entrée un vecteur
separation: 'a vect -> int -> int -> int = <fun>
function separation(var v: tableau ; i1, i2: integer): integer;
I.C.3) Écrire une fonction tri_rapide réalisant le tri d'un vecteur/tableau en appliquant l'algorithme décrit plus haut.
II Étude de complexité
On s'intéresse maintenant à la complexité du tri rapide dans deux cas particuliers.
II. - Donner un ordre de grandeur du nombre de comparaisons effectuées lorsque le tableau est déjà trié dans l'ordre croissant (respectivement décroissant). Sans forcément donner un équivalent de ce nombre de comparaison
, on donnera (en justifiant) une valeur simple
telle que
et
.
II.B - On suppose ici que lors d'une exécution du tri rapide, chaque séparation du tableau a coupé le tableau en deux parts égales.
II.B.1) Montrer qu'un majorant raisonnable du nombre de comparaisons effectuées pour trier un tableau de taille vérifie une relation de la forme
.
II.B.2) Donner (en fonction de ) la valeur de
lorsque
est de la forme
avec
.
II.B.3) On ne suppose plus, ici, que est de la forme
. Montrer que, si on suppose que
est croissante, alors
.
II.
II.B - On suppose ici que lors d'une exécution du tri rapide, chaque séparation du tableau a coupé le tableau en deux parts égales.
II.B.1) Montrer qu'un majorant raisonnable du nombre de comparaisons effectuées pour trier un tableau de taille
II.B.2) Donner (en fonction de
II.B.3) On ne suppose plus, ici, que
III Recherche d'une pseudo médiane
Ce qui précède suggère que le choix d'un pivot « proche de la médiane» permet d'améliorer les performances du tri rapide. Il existe un algorithme permettant de trouver cette médiane en un temps linéaire en la taille du tableau, mais cet algorithme difficile ne sera pas discuté ici. Une façon simple pour lutter contre le pire des cas consiste à choisir le pivot de façon aléatoire, mais le gain obtenu est relativement subtil et le pire des cas reste quadratique. Une méthode intermédiaire consiste à rechercher une «pseudo médiane».
Lorsque , une
-pseudo médiane d'un tableau est une valeur présente dans le tableau telle qu'au moins
(respectivement
) éléments du tableau lui sont inférieurs (respectivement supérieurs), avec
et
deux constantes strictement positives.
Pour un tableau de taille , on utilisera l'algorithme de recherche d'une pseudo médiane suivant :
Lorsque
Pour un tableau de taille
- si
, on retourne directement le seul élément considéré; - sinon, on regroupe les éléments du tableau par 3 , on calcule les
médianes de ces groupes, puis on applique récursivement l'algorithme à ces valeurs.
Dans les questions III.A et III.B, on admet que cet algorithme permet le calcul d'une pseudo médiane et on propose de le mettre en œuvre de deux manières différentes.
On rappelle que les différents éléments du tableau pourront être supposés distincts.
On rappelle que les différents éléments du tableau pourront être supposés distincts.
III.A - Dans un tableau, en place
III.A.1) Écrire une fonction prenant en entrée un tableau et trois indices distincts et retournant la position de la médiane, parmi les trois éléments du tableau dont on a donné les indices.
III.A.2) Écrire une fonction calculant une pseudo médiane. Cette fonction travaillera obligatoirement dans le tableau initial, sans en créer de nouveau, et en maintenant globalement invariant l'ensemble des valeurs présentes dans le tableau.
III.A.2) Écrire une fonction calculant une pseudo médiane. Cette fonction travaillera obligatoirement dans le tableau initial, sans en créer de nouveau, et en maintenant globalement invariant l'ensemble des valeurs présentes dans le tableau.
On pourra supposer le tableau de taille
, placer dans une première étape les médianes de blocs de trois en positions
, puis prendre les médianes de ces médianes et les placer en position
, etc.
III.B - À l'aide d'un arbre ternaire
On propose de construire un arbre ternaire : les feuilles sont étiquetées par les entrées du tableau et chaque nœud interne est la médiane de ses fils. La figure 1 montre l'arbre construit sur le tableau
.

Figure 1
En Caml :
type ternaire=F of int | N of intternaireternaire*ternaire; ;
let racine=function ; ;
En Pascal :
type
Arbre =
Noeud = record
racine: integer;
fg, fm, fd: Arbre;
end;
III.B.1) Écrire une fonction calculant la médiane de trois entiers distincts.
let racine=function
En Pascal :
type
Arbre =
Noeud = record
racine: integer;
fg, fm, fd: Arbre;
end;
III.B.1) Écrire une fonction calculant la médiane de trois entiers distincts.
mediane3 : int * int * int -> int = <fun>
function mediane3(i1, i2, i3 : integer) : integer;
III.B.2) Écrire une fonction prenant en entrée trois arbres ternaires et retournant l'arbre ternaire dont la racine est étiquetée par la médiane des trois racines des arbres donnés en entrée et a pour fils ces trois arbres.
III.B.3) Écrire une fonction récursive construisant l'arbre ternaire associé à un sous-tableau de taille . En Caml, construire t i j retourne l'arbre du sous-tableau
. Même chose en Pascal avec construire (
)
III.B.3) Écrire une fonction récursive construisant l'arbre ternaire associé à un sous-tableau de taille
construire : int vect -> int -> int -> ternaire = <fun>
function construire(t: tableau ; i, j: integer): Arbre;
III.B.4) Écrire une fonction calculant, à l'aide d'un arbre ternaire, une pseudo médiane d'un tableau (dont la longueur pourra être supposée de la forme
).
III.C - Étude théorique de l'algorithme
III.C.1) Donner un ordre de grandeur du temps d'exécution de l'algorithme de calcul d'une pseudo médiane.
III.C.2) Si , la valeur retournée est exactement la médiane du tableau. Montrer que pour
, il existe au moins
éléments du tableau qui sont majorés (au sens large) par la valeur retournée.
III.C.3) Montrer que pour tout , il existe un tableau pour lequel il y a exactement
éléments du tableau qui sont majorés (au sens large) par la valeur retournée.
III.C.4) Prouver que cet algorithme permet de calculer une -pseudo médiane, avec
.
III.C.5) Expliquer comment adapter l'implémentation de l'algorithme si le tableau a une longueur qui n'est pas une puissance de 3 ?
III.C.2) Si
III.C.3) Montrer que pour tout
III.C.4) Prouver que cet algorithme permet de calculer une
III.C.5) Expliquer comment adapter l'implémentation de l'algorithme si le tableau a une longueur qui n'est pas une puissance de 3 ?
III.D - Extensions du principe de l'algorithme
III.D.1) Si on modifie l'algorithme en considérant des blocs de 5 éléments plutôt que 3, que dire (en supposant que la longueur du tableau est une puissance de 5) du résultat retourné et du temps de calcul de ce nouvel algorithme?
III.D.2) Montrer que pour tout , il existe un algorithme s'exécutant en un coût linéaire et permettant de calculer une
-pseudo médiane d'un tableau.
III.D.2) Montrer que pour tout
IV Gain apporté par la pseudo médiane
On s'intéresse enfin au gain qu'apporte l'utilisation de pseudo médianes dans le tri rapide. On suppose ici (sauf à la dernière question) que le tri rapide est exécuté en utilisant à chaque étape une
pseudo médiane. Ici encore, une analyse précise et rigoureuse de la complexité est délicate, mais on souhaite obtenir une évaluation de façon raisonnablement convaincante.
On note le temps de calcul dans le pire des cas pour appliquer le tri rapide avec une
-pseudo médiane. Dans cette évaluation en première approximation, on s'autorise à écrire
même lorsque
n'est pas entier : ce sera un raccourci pour
, avec
la «partie entière supérieure de
.
IV.A - Justifier qualitativement le fait que vérifie une inégalité de la forme
On note
IV.A - Justifier qualitativement le fait que
IV.B - Montrer que
.
On pourra étudier la suite définie par
et
si
(et
sinon) : établir par exemple que
si
.
IV.C - Conclure.
IV.D - Que peut-on raisonnablement espérer comme complexité dans le pire des cas, pour un tri rapide effectué en calculant une ln -pseudo médiane avec l'algorithme de la partie III?
IV.C - Conclure.
IV.D - Que peut-on raisonnablement espérer comme complexité dans le pire des cas, pour un tri rapide effectué en calculant une ln
