Vous êtes sur la page 1sur 9

Universit´e Paris Diderot Licence Informatique

Programmation Orient´ee Objet Ann´ee 2008-2009

TP n 2 - Correction

Piles, Tri et Entrepot

Dans ce TD on va faire un simple exercice de programmation ave c des classes. On en profi- tera ´egalement pour commencer `a se familiariser avec l’environnement de d´eveloppement eclipse . Eclipse, comme emacs, permet d’´ecrire des fichiers .java, m ais il a beaucoup plus de fonction- nalit´es, qui rendent la programmation plus rapide et organis´ee, et permettent de trouver les erreurs et de tester les programmes plus facilement. Vous pouvez commencer `a utiliser eclipse comme ´editeur, e t d´ecouvrir au fur et `a mesure ses fonctionnalit´es. Lancez ecplise `a partir d’un terminal. Choisissez un r´epertoire `a utiliser comme ”workspace” par exemple ”POO”. Cr´eez un projet java ”TP2”. Cela cr´eera un r´epertoire ”TP2” qui contient les fichiers .java et les fichiers .class Eclipse vous permet de compiler et ex´ecuter vos programmes sans passer par le termi- nal. Une br`eve introduction `a eclipse, r´ealis´ee par Julien Cervelle, peut ˆetre consult´ee `a :

www.enseignement.polytechnique.fr/informatique/profs/Julien.Cervelle/eclipse/ Un cours facultatif d´edi´e aux environnements de d´eveloppement sera ´egalement disponible au deuxi`eme semestre. Dans les exercices qui suivent, on va utiliser la classe Scanner, qui a et´e introduite `a partir de la version java 1.5.0. Elle simplifie la lecture de donn´ees sur l’entr´ee standard (clavier) ou dans un fichier. Nous parlerons ici simplement de la lecture au clavier. Pour utiliser la classe Scanner, il faut d’abord l’importer :

import java.util.Scanner; Ensuite il faut cr´eer un objet de la classe Scanner :

Scanner sc = new Scanner(System.in);

Pour r´ecup´erer les donn´ees, il faut faire appel sur l’objet sc aux m´ethodes d´ecrites ci-dessous. Ces m´ethodes parcourent la donn´ee suivante lue sur l’entr´ee et la retourne :

String next() : donn´ee de la classe String qui forme un mot,

String nextLine() : donn´ee de la classe String qui forme une ligne,

boolean nextBoolean() : donn´ee bool´eenne,

int nextInt() : donn´ee enti`ere de type int,

double nextDouble() : donn´ee r´eelle de type double.

Il peut ˆetre utile de v´erifier le type d’une donn´ee avant de la lire :

boolean hasNext() : renvoie true s’il y a une donn´ee `a lire,

boolean hasNext(String pattern) : renvoie true si la prochaine donn´ee `a lire forme le mot pattern,

boolean hasNextLine() : renvoie true s’il y a une ligne `a lire,

boolean hasNextBoolean() : renvoie true s’il y a un bool´een `a lire,

boolean hasNextInt() : renvoie true s’il y a un entier `a lire,

boolean hasNextDouble() : renvoie true s’il y a un double `a lire.

Il existe d’autres m´ethodes de la classe Scanner. Si cela vo us int´eresse, allez consulter l’API de java. Dans les exercices que suivent on utilisera la class e scanner pour les saisies au clavier.

1

´

Exercice 1 [Piles] Ecrire une classe implantant une pile d’´el´ements. On consid`ere qu’un ´el´ement

de pile encapsule une valeur enti`ere.

1. D´efinir la classe ElementPile qui repr´esente un ´el´ement d’une pile. Les attributs de cette classe seront priv´es. D´efinir les constructeurs et les acc esseurs de cette classe.

2. Comment repr´esenter la pile vide ?

3. D´efinir la classe Pile. Le constructeur de cette classe construira la pile vide.

4. D´efinir une m´ethode permettant de tester si une pile est vide.

5. D´efinir la m´ethode empile(ajoute un ´el´ement au sommet de la pile)

6. D´efinir la m´ethode depile (retourne le sommet et le retire de la pile)

7. D´efinir la m´ethode sommet (retourne le sommet de la pile sans le retirer)

8. D´efinir dans la classe Pile la m´ethode affiche qui affiche le contenu d’une pile, sans la modifier.

Tester la cr´eation d’une pile et sa manipulation en empilant puis d´epilant divers ´el´ements

Correction :

d´ebut Pile.java

public class Pile { private int pos; // position dans le tableau private ElementPile [] p;

public Pile () { // creation d’une pile vide de taille 10

p = new ElementPile[10]; pos = 0;

}

public Pile (int taille) { // creation d’un pile vide de taille donnee

p = new ElementPile[taille];

}

public void empile (ElementPile e) { if (pos == p.length) { // plus d’expace ElementPile[] tmp = new ElementPile[p.length+10]; for (int i = 0; i < p.length; i++) tmp[i] = p[i]; p = tmp;

}

p[pos++] = e;

}

public ElementPile depile () { return p[--pos];

}

public ElementPile sommet () { return p[pos-1];

}

public boolean estVide () { return pos == 0;

}

public void affiche () { System.out.print("Pile: ["); for (int i = pos-1; i >= 0; i--) p[i].affiche ();

2

System.out.println (" ]");

}

}

fin Pile.java d´ebut ElementPile.java

public class ElementPile { private int valeur;

public ElementPile () { this.valeur = 0;

}

public ElementPile (int valeur) { this.valeur = valeur;

}

public int getValue () { return valeur;

}

public void affiche () { System.out.print (" "+valeur);

}

}

fin ElementPile.java

´

Exercice 2 [Tri par insertion et piles] Ecrire un programme de tri par insertion d’un ensemble de nombres entiers. Les donn´ees sont stock´ees dans une pil e A et le programme doit retourner

une pile B contenant ces nombres tri´es avec le minimum au som met de la pile. L’algorithme propos´e est le suivant : on utilise une pile C qui est vide au d´ebut. Tant que la pile A n’est pas vide, on consid`ere les deux cas suivants :

– si la pile B est vide ou si l’´el´ement au sommet de A est plus p etit que celui de B :

on retire l’´el´ement au sommet de la pile A pour empiler dans la pile B, puis si la pile C n’est pas vide on retire tous les ´el´ements de la pile C pour e mpiler dans la pile B.

– sinon :

on deplace l’´el´ement au sommet de la pile B `a la pile C. D´efinir une classe Tri qui contient trois piles A, B et C, une m´ethode tri(Pile A, pile B, Pile C)

et la m´ethode main(). La pile A peut ˆetre construite `a partir d’un tableau d’entiers en utilisant

la

m´ethode empile. Tester avec la pile A = { 4 , 3 , 2 , 5 , 8 , 2 , 6 , 9 , 3 } .

Correction :

public class Tri {

d´ebut Tri.java

private Pile A, B, C;

private void tri () { while (!A.estVide()) { if (B.estVide() || B.sommet().getValue() > A.sommet().getValue()) { B.empile(A.depile()); while (!C.estVide()) B.empile(C.depile());

3

}

else C.empile(B.depile());

}

}

public Pile tri(Pile A, Pile B, Pile C) { this.A = A; this.B = B; this.C = C; tri(); return B;

}

}

fin Tri.java

Exercice 3 Soit la classe Produit d´efinie par un nom, un prix et le nombre de jours restant avant p´eremption du produit. Soit la classe Entrepot d´efinie par un ensemble de produits et le nombre de produits p´erim´es. L’ensemble sera vu comme une pile. Vous aurez par ailleurs `a utiliser les m´ethodes de la classe Pile. La classe Pile doit ˆetre modifi´ee pour g´erer les objet Produit On appelera cette modifi- cation PileEntrepot

´

1. Ecrire la m´ethode construitEntrepot qui construit un ensemble `a partir de donn´ees

entr´ees au clavier.

´

2. Ecrire la m´ethode trie qui trie un ensemble suivant la date de p´eremption en pla¸cant en

haut de la pile le produit dont le nombre de jour avant p´eremption est le plus faible (ce nombre peut ˆetre n´egatif).

´

3. Ecrire la m´ethode suppression qui ˆote de l’ensemble tous les produits p´erim´es et renvoi e

la somme perdue.

´

4. Ecrire les m´ethodes qui r´ealisent l’union, union, et l’intersection, intersection, tri´ees de

deux ensembles tri´es. Attention `a la valeur de la variable comptant le nombre de produits p´erim´es.

Correction :

class Produit { private String nom; private double prix; private int peremption;

d´ebut Produit.java

Produit(String name, double price, int expire){ nom = new String(name); prix = price; peremption = expire;

}

Produit(Produit e){ nom = new String(e.nom); prix = e.prix; peremption = e.peremption;

}

4

int getValue(){ return peremption;

}

double getPrix(){ return prix;

}

boolean egale(Produit p){ return((nom.equals(p.nom)) && (prix == p.prix) && (peremption == p.peremption));

}

public void affiche () { System.out.println("nom: "+nom+", prix: "+prix+", peremption: "+peremption);

}

}

fin Produit.java d´ebut Entrepot.java

import java.util.*; import java.io.*;

class Entrepot{ PileEntrepot ensemble; int perime;

Entrepot(){ ensemble = new PileEntrepot(); perime = 0;

}

void construitEntrepot(){ Scanner sc = new Scanner(System.in);

System.out.println("Entrer les produits (nom prix peremption) et taper stop lorsque vous avez t while(!(sc.hasNext("stop"))){ ensemble.empile(new Produit(sc.next(),sc.nextDouble(),sc.nextInt()));

if(ensemble.sommet().getValue()<=0)

}

}

perime++;

void tri(){ TriEntrepot t = new TriEntrepot(); ensemble=t.tri(ensemble, new PileEntrepot(),new PileEntrepot());

}

double suppression(){ double sommePerdue = 0;

while(ensemble.sommet().getValue()<=0){

sommePerdue += ensemble.depile().getPrix(); perime++;

}

5

return sommePerdue;

}

Entrepot union(Entrepot e){ PileEntrepot temp=new PileEntrepot(); Entrepot res=new Entrepot();

while(!(ensemble.estVide()) && !(e.ensemble.estVide())){ if(ensemble.sommet().egale(e.ensemble.sommet())){ temp.empile(ensemble.depile()); e.ensemble.depile();

}

else

if(ensemble.sommet().getValue() < e.ensemble.sommet().getValue()) temp.empile(ensemble.depile());

else

temp.empile(e.ensemble.depile());

res.perime++;

}

if(ensemble.estVide())

while(!(e.ensemble.estVide())){

temp.empile(e.ensemble.depile());

res.perime++;

}

else

while(!(ensemble.estVide())){

temp.empile(ensemble.depile());

res.perime++;

}

while(!(temp.estVide()))

res.ensemble.empile(temp.depile());

return res;

}

Entrepot intersection(Entrepot e){ PileEntrepot temp=new PileEntrepot(); Entrepot res=new Entrepot();

while(!(ensemble.estVide()) && !(e.ensemble.estVide())){ if(ensemble.sommet().egale(e.ensemble.sommet())){ temp.empile(ensemble.depile()); res.perime++;

}

else

if(ensemble.sommet().getValue() < e.ensemble.sommet().getValue()) ensemble.depile();

else

e.ensemble.depile();

}

while(!(temp.estVide()))

res.ensemble.empile(temp.depile());

return res;

6

}

void affiche(){ ensemble.affiche();

}

public static void main(String[] args){ Entrepot e = new Entrepot(), f = new Entrepot(), g = new Entrepot(); e.construitEntrepot(); e.affiche(); e.tri(); e.affiche(); System.out.println("somme perdue: "+e.suppression()); e.affiche(); f.construitEntrepot(); f.tri(); System.out.println("union: "); e=e.union(f); e.affiche(); System.out.println("perime: "+e.perime); g.construitEntrepot(); g.tri(); g.affiche(); System.out.println("intersection: "); e=e.intersection(g); e.affiche(); System.out.println("perime: "+e.perime);

}

}

fin Entrepot.java d´ebut PileEntrepot.java

public class PileEntrepot { private int pos; // position dans le tableau private Produit [] p;

public PileEntrepot () { // creation d’une pile vide de taille 10

p = new Produit[10]; pos = 0;

}

public PileEntrepot (int taille) { // creation d’un pile vide de taille donnee

p = new Produit[taille];

}

public void empile (Produit e) { if (pos == p.length) { // plus d’expace Produit[] tmp = new Produit[p.length+10]; for (int i = 0; i < p.length; i++) tmp[i] = p[i]; p = tmp;

}

p[pos++] = e;

}

public Produit depile () { return p[--pos];

7

}

public Produit sommet () { return p[pos-1];

}

public boolean estVide () { return pos == 0;

}

public void affiche () { System.out.print("Pile: ["); for (int i = pos-1; i >= 0; i--) p[i].affiche (); System.out.println (" ]");

}

}

fin PileEntrepot.java

Exercice 4 [Jeu des Tours de Hanoi] Pour ceux qui ont encore du temps

´

Etant donn´e trois piles, et n disques de tailles diff´erentes empil´es sur la premi`ere, l es plus petits au dessus des plus grands :

Un d´eplacement consiste `a choisir une pile A non vide, et `a enlever le disque au sommet pour le mettre au sommet d’une autre pile B, si le sommet de cette pile n’est pas un disque plus petit (sinon, le d´eplacement est impossible). On veut d´eplacer tous les disques de la premi`ere pile sur la seconde, en se servant de la derni`ere. L’algorithme propos´e est le suivant : Pour d´eplacer n disques de la pile A sur la pile C en utilisant la pile B, on d´eplace (r´ecursivement) n 1 disques de A vers B, puis on d´eplace le disque restant sur le sommet de la pile A vers la pile C, et on d´eplace (r´ecursivement) n 1 disques de B vers C. D´efinir une classe Hanoi qui repr´esente le jeu : trois piles et le nombre de disques. D´efinir le constructeur qui initialise le jeu `a partir d’un nombre de disques `a empiler et initialise les piles dans la situation de d´epart. D´efinir la m´ethode affiche qui affiche le contenu des piles. D´efinir la m´ethode priv´ee deplace et la m´ethode joue qui lance le jeu. Enfin, d´efinir la m´ethode statique main qui `a partir d’un entier saisi en ligne de commande initialise et lance le jeu.

Pour visualiser plus agr´eablement le d´eroulement du jeu, modifier la m´ethode deplace afin d’afficher l’´etat du jeu apr`es chaque d´eplacement. On vous propose d’utiliser une classe Afficheur qui propose un affichage un peu ´elabor´e et quelques options p our le d´eroulement du jeu. Modifier la classe Hanoi en ajoutant un champ de type Afficheur. Le constructeur devra prendre en param`etre un objet de ce type et l’affecter a votre champ. Remplacer le contenu de la m´ethode affiche en effectuant simplement un appel `a la m´ethode afficher de l’ Afficheur qui prend en param`etre les trois piles puis le nombre de disques. Compiler le tout et lancer le jeu en ex´ecutant le main de la classe Afficheur.

Correction :

public class Hanoi { private Afficheur aff; private Pile A, B, C; private int nbDisques;

d´ebut Hanoi.java

8

public Hanoi (int nbDisques, Afficheur aff) { this.aff = aff; this.nbDisques = nbDisques;

A = new Pile();

B = new Pile ();

C = new Pile ();

for (int i = nbDisques; i > 0; i--) A.empile(new ElementPile (i));

}

public void affiche () { aff.affiche(A, B, C, nbDisques);

}

private void deplace (Pile src, Pile dest, Pile tmp, int n) { if (n > 0) { deplace(src, tmp, dest, n-1); dest.empile(src.depile()); affiche(); deplace(tmp, dest, src, n-1);

}

}

public void joue () { deplace (A, B, C, nbDisques);

}

}

fin Hanoi.java

9