TD 7 : Tris rapides




Les méthodes de tous les exercices doivent être écrites dans les classes fournies en annexe.



EXERCICE 1

On considère les tas décroissants (resp. croissants) étudiés en cours.

Ecrivez intégralement la classe TasDecroissant (resp. TasCroissant), classe dont les instances sont les tas vus en cours.

Ecrivez la classe TriTas qui implémente le tri par tas vu en cours.


EXERCICE 2

On considère un tas (croissant ou décroissant) ne contenant que des objets de clefs distinctes. On désire pouvoir supprimer un élément de clef donnée dans un tel tas tout en conservant au tas sa propriété de tas.

Ecrivez la méthode publique extraire(int k) de la classe TasDecroissant (resp. TasCroissant), méthode qui supprime l'élément de clef k dans un tas décroissant (resp. croissant).

Que pensez-vous de la méthode précédente si maintenant on désire supprimer tous les éléments d'une clef donnée dans un tas pouvant contenir plusieurs éléments de même clef ?


EXERCICE 3

Un tas (croissant ou décroisssant) d-aire (d > 1) est un tas représenté par un arbre parfait d-aire, c'est à dire un arbre parfait dont les noeuds ont au plus d fils. A la manière des arbres parfaits binaires (d = 2), un arbre parfait d-aire peut être représenté par un tableau,

Expliquez comment on peut représenter un arbre parfait d-aire à l'aide d'un tableau et donnez le numérotage des noeuds en fonction de d.

Calculez la hauteur d'un tas d-aire de n éléments en fonction de n et de d et donnez la complexité des méthodes appliquées sur ce tas.

En vous inspirant largement de la classe TasDecroissant, écrivez la classe TasDaireDecroissant (resp. TasDaireCroissant) qui implémente les tas d-aire.




EXERCICE 4

On veut écrire une version du tri rapide basée sur une méthode de partitionnement qui partitionne une tranche de tableau en trois parties (et non deux parties comme la méthode étudiée en cours). Le comportement de la nouvelle méthode partitionnerEnTrois de la classe PartitionTernaire est le suivant : étant donné un tableau T et deux indices i et j tels ques i < j, partitionner(i,j) déplace éventuellement des objets dans T et retourne deux indices g et d (sous la forme d'un tableau P à deux éléments avec P[0] = g et P[1] = d) tels que g < d, et qui partagent la tranche T[i..j] en trois parties comme suit :

avec T[g] £ T[d], et " x Î T[i..g-1], " y Î T[g+1..d-1], " z Î T[d+1..j], on a :
x < T[g], T[g] £ y, y < T[d] et T[d] £ z
x < y signifie x.clef() < y.clef() si x et y sont deux objets à clef.



En utilisant la méthode partitionnerEnTrois de la classe PartitionTernaire, écrivez les méthodes trier de la classe TriRapideTernaire, telles que t.trier() trie le tableau contenu dans l'objet t en place par la méthode du tri rapide.

Que pensez-vous de la complexité de la méthode trier de la classe TriRapideTernaire par rapport à celle de la méthode trier étudiée en cours ?

En utilisant la méthode partitionner de la classe PartitionTernaire (la méthode étudiée en cours), écrivez le corps de la méthode partitionnerEnTrois de la classe PartitionTernaire.

En vous inspirant de la méthode partitionner, réécrivez le corps de la méthode partitionnerEnTrois de la classe PartitionTernaire.


EXERCICE 5

On dit qu'un tableau est presque triée à l'ordre k (k ³ 1) si, en le découpant suivant les indices multiples de k, les tranches ainsi obtenues sont globalement triées par ordre croissant. Par exemple, considérons le tableau suivant (seules les clefs des éléments apparaissent) :

Il est presque trié à l'ordre 4, car si on considère les tranches de longueur 4 (sauf peut-être la dernière de longueur inférieure ou égale à 4), elles sont globalement ordonnées (i.e. si on considère deux tranches consécutives, un élément quelconque de la première est inférieur ou égal à un élément quelconque de la deuxième).

Ecrivez la méthode publique presqueTrie de la classe PresqueTrier telle que t.presqueTrie(k) (avec k ³ 1) retourne true si le tableau contenu dans l'objet t est presque triée à l'ordre k.

Soient i et j deux entiers tels que i < j, et un entier k, k ³ 1. Ecrivez la méthode privée estInclus de la classe PresqueTrier telle que estInclus(i,j,k) teste si l'intervalle [i,j] (i £ j) est inclus dans un intervalle [a,b[ où a et b sont deux multiples de k consécutifs (par exemple, estInclus(13,15,4) retourne true car [13,15] Í [12,16[, et 12 et 16 sont deux multiples de 4 consécutifs).

Ecrivez la méthode presqueTrier de la classe PresqueTrier telle que l'exécution de t.PresqueTrier(k) (k ³ 1), réarrange le tableau contenu dans l'objet t de façon à ce qu'il soit presque trié à l'ordre k.


EXERCICE 6

On désire implémenter la méthode de tri par fusion. Comme le tri rapide, cette méthode utilise la technique ``diviser pour régner'' pour effectuer un tri avec une complexité en Q(n lg(n)) où n est la taille du tableau à trier. L'inconvénient de cette méthode est qu'elle nécessite l'utilisation d'un tableau temporaire de la taille du tableau à trier.

Ecrivez toutes les méthodes de la classe TriFusion de manière que t.trier() trie le tableau contenu dans l'objet t avec une complexité de Q(n lg(n)) où n est la taille de ce tableau.


EXERCICE 7

La partie délicate du tri rapide est la méthode de partition. L'écriture de cette méthode est plus simple si on dispose d'un tableau temporaire en plus du tableau à trier. Le tri n'est alors plus en place, mais conserve néanmoins sa bonne complexité.

Ecrivez la méthode partionnerDans de la classe TriRapideNEP telle que partitionnerDans(A,B,i,j) partitionne la tranche de tableau A[i..j] dans la tranche de tableau B[i..j] et retourne l'indice du pivot.

En définissant autant de méthodes privées que nécessaire, écrivez la méthode trier de la classe TriRapideNEP telle que t.trier() trier le tableau contenu dans l'objet t par la méthode du tri rapide en utilisant un tableau temporaire.


EXERCICE 8

Une compagnie pétrolière projette de construire un oléoduc d'Est en Ouest à travers un champ pétrolier contenant n puits de pétrole. Chaque puits doit être raccordé à l'oléoduc principal à l'aide d'un petit oléoduc orienté Nord-Sud, perpendiculaire à l'oléoduc principal. On connaît les coordonnées de chaque puits dans un repère cartésien d'abscisse Est-Ouest et d'ordonnée Nord-Sud et chaque puits a une abscisse et une ordonnée unique. On cherche l'emplacement de l'oléoduc principal (une droite) qui minimise la longueur totale des raccordements :
En supposant que deux puits distincts ont leurs coordonnées deux à deux distinctes, expliquez comment cet emplacement peut être calculé en O(n).


EXERCICE 9

On désire écrire une version du calcul d'un rang statistique à l'aide de la méthode de partition élaborée à l'exercice 4.

En utilisant la méthode partitionnerEnTrois de l'exerice 4, écrivez la méthode rang de la classe RangEnTrois, telle que r.rang(k) retourne le k-ième rang statistique du tableau contenu dans r.


This document was translated from LATEX by HEVEA.