LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con...

33
LIP: 19 Aprile 2005

Transcript of LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con...

Page 1: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

LIP: 19 Aprile 2005

Page 2: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Contenuto

• Soluzione Compitino

• Tipo di dato MultiSet, estensione con sottoclasse

Page 3: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Primo EsercizioSi implementi (con una rappresentazione privata) la seguente specifica del tipo di dato PairInt

public class PairInt {// OVERVIEW: un PairInt è una coppia di interi. Elementotipico: //(x,y); è modificabile.// costruttorepublic PairInt (int x,int y) {// EFFECTS: costruisce un nuovo PairInt che rappresenta(x,y)}//metodipublic int left() {// EFFECTS: restituisce il primo elemento della coppiathis.}public int right() {// EFFECTS: restituisce il secondo elemento della coppiathis.}public void incr(int x,int y) {//MODIFIES:this// EFFECTS: modifica this, sommando x al primo elemento edy al secondo elemento della coppia.}}

Page 4: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Facilepublic class PairInt {private int left;private int right;

public PairInt (int x,int y) {left=x;right=y;}public int left() {return left; }public int right() {return right;}public void incr(int x,int y) {left=left+ x; right=right+ y;}}

Page 5: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Tester di PairInt

public class Tester{public static void main(String[] args) {PairInt p1=new PairInt(2,4);PairInt p2=new PairInt(6,9);System.out.println(p1.left());System.out.println(p1.right());p1.incr(p2.left(),p2.right());System.out.println(p1.left());System.out.println(p1.right());

}}

Page 6: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Secondo Esercizio•Si implementi (con una rappresentazione privata) la seguente specifica del tipo di dato PairQueue

•Coda (mantiene gli elementi in ordine FIFO)

•Gli elementi sono coppie di interi (PairInt)

Ex: (3,5), (9,0),(4,6)

(3,5) primo inserito (primo della coda) (4,6) ultimo inserito

Page 7: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class PairQueue {// OVERVIEW: un PairQueue è una coda di elementi, che sono coppie di interi (tipo PairInt); gli elementi //sono ordinati in base all’ordine di inserimento secondo una politica first-in-first-out. è modificabile.

// costruttorepublic PairQueue () {// EFFECTS: costruisce un nuovo PairQueue vuoto.}

//metodipublic void dequeue () throws EmptyException {//MODIFIES:this// EFFECTS: se this e’ vuoto solleva EmptyException, altrimenti rimuove il primo elemento di this.}

public PairInt first () throws EmptyException {// EFFECTS: se this e’ vuoto solleva EmptyException, altrimenti restituisce il primo elemento di this.}

public void enqueue (PairInt p) throws NullPointerException {//MODIFIES:this// EFFECTS: se p e’ null solleva NullPointerException, altrimenti //inserisce p in this.}

public String toString () {

// EFFECTS: restituisce una stringa che rappresenta il contenuto di this, ovvero la sequenza ordinata delle coppie.}

Page 8: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Implementazione

• Facile: usando un Vector

• Simile alla pila, basta inserire da una parte e

rimuovere dall’altra

• Bisogna definire anche la classe che definisce l’eccezione EmptyException

Page 9: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Eccezione Controllata

public class EmptyException extends Exception{

public EmptyException(String s) {super(s);}

}

Page 10: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class PairQueue{

private Vector coda;

public PairQueue () {coda=new Vector();}public void dequeue () throws EmptyException {if (coda.size()==0) throw new EmptyException("PairQueue.first");coda.removeElementAt(0);}public PairInt first () throws EmptyException {if (coda.size()==0) throw new EmptyException("PairQueue.first");return (PairInt) coda.elementAt(0);

}public void enqueue (PairInt p) throws NullPointerException {coda.addElement(p);}public String toString () {String s="";for (int j=0; j< coda.size();j++){PairInt x=(PairInt) coda.elementAt(j);s=s + "(" + x.left() + "," + x.right() + ")";}return s;}}

Page 11: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Tester

• Si puo’ procedere in modo incrementale estendendo quello di prima

• Provare i metodi che inseriscono e rimuovono

• toString fondamentale per testing (dato che la rappresentazione e’ privata non avrei modo altrimenti di guardare il contenuto della coda)

• Bisogna testare anche il caso vuoto per vedere che i metodi lancino l’eccezione

Page 12: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class Tester{public static void main(String[] args) throws EmptyException{PairInt p1=new PairInt(2,4);PairInt p2=new PairInt(6,9);System.out.println(p1.left());System.out.println(p1.right());p1.incr(p2.left(),p2.right());System.out.println(p1.left());System.out.println(p1.right());

PairQueue q=new PairQueue();q.enqueue(p2);q.enqueue(p1);System.out.println(q.toString());PairInt p3=q.first();System.out.println(p3.left());System.out.println(p3.right());q.dequeue();q.dequeue(); // e’ vuota: il main solleva l’eccezione?try{q.first();} //altrimenti tutto termina sollevando l’eccezione (deve comunque esserecatch (EmptyException e) // riportata nel throws per compilarlo (controllata){System.out.println("VUOTA");}

}

Page 13: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Terzo Esercizio

• Definire una classe nuova che contiene una procedura statica per modificare PairQueue

public class PairQueueProc {

// metodi statici

public static PairQueue append (Pairqueue p,PairQueue q) throws NullPointerException {

// EFFECTS: se p o q sono null solleva NullPointerException, altrimenti restituisce un nuovo PairQueue che e’ la concatenazione di p e q in cui tutte le coppie sono state //incrementate di 1. Esempio: dati p=(3,6),(4,8) e q=(7,9), restituisce s=(4,7),(5,9),(8,10). }

}

Page 14: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Problema

• Va scritta usando la specifica di PairQueue (anche se la rappresentazione c’e’ non puo’ accedervi perche’ e’ privata)

• Non deve modificare le code p e q passate per parametro dato che nella specifica di append non e’ riportato (non c’e’ MODIFIES)

• Se le modificasse l’implementazione violerebbe la specifica

• Problema grave: se l’implementazione non soddisfa la specifica, la

specifica sarebbe inutile (chi usa append dovrebbe andare a vedere l’implementazione per sapere cosa fa (se le modifica o no)

• Si perderebbe il meccanismo di astrazione tramite specifica che e’ la base della programmazione modulare

Page 15: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public static PairQueue append (PairQueue p,PairQueue q) throws NullPointerException {if (p==null || q==null) throw new NullPointerException("append");

PairQueue s=new PairQueue();PairQueue p1=new PairQueue(); \\ per memorizzare pPairQueue q1=new PairQueue(); \\ per memorizzare qtry{while(true){PairInt x = p.first();p1.enqueue(new PairInt(x.left(),x.right()));x.incr(1,1);s.enqueue(x);p.dequeue();}}catch (EmptyException e1){p=p1;System.out.println("termina1");} \\ ripristino p

try{while(true){PairInt y = q.first();q1.enqueue(new PairInt(y.left(),y.right()));y.incr(1,1);s.enqueue(y);q.dequeue();}}catch (EmptyException e2){System.out.println("termina2");q=q1; } \\ ripristino qreturn s; }}

Page 16: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Nuovo Esercizio

• Variante di IntSet (visto a lezione di MP)

• Definiamo MIntSet• Sono multiinsiemi di interi

•Insieme: collezione di elementi, non esiste il concetto di numero di occorrenze (Ex. {1,7,8})•Multiinsieme: collezione di elementi, che possono occorrere zero o piu’ volte (Ex. {1,7,8,7,1,1}).

Page 17: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Operazioni su Multiset

•Le operazioni sono analoghe a quelle degli insiemi solo cheaggiungono e rimuovono una occorrenza

•Analogamente per unione ed intersezione (quando unisco Faccio la somma del numero di occorrenze, quando interseco prendo per ogni elemento solo il numero di occorrenze che sta in entrambi)

•Vediamo la specifica

Page 18: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class IMultiset {//OVERVIEW: un IMultiset e' un multiinsieme di interi ( in//cui ogni elemento puo' occorrere piu' volte), es. {1,5,4,1,4}.//E' modficabile

//metodi e costruttori public IMultiset () {//EFFECTS: inizializza this al multiinsieme vuoto}

public int isin(int x) {//EFFECTS: restituisce il numero di occorrenze di x (0 se non compare)}

public void insert(int x){//EFFECTS: inserisce un’occorrenza di x in this//MODIFIES: this}

public void remove(int x){//EFFECTS: rimuove una occorrenza di x da this (se non c’e’ non fa nulla)//MODIFIES: this }

Page 19: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public String toString(){//EFFECTS: restituisce una stringa che contiene l’insieme this}

public void union(IMultiset x){//EFFECTS: modifica this, facendo this unione x//MODIFIES: this}

public void inter(IMultiset x){//EFFECTS: modifica this, facendo this intersecato x//MODIFIES: this}

}

Page 20: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Implementazione

• La scelta fondamentale e’ quella della rappresentazione

• Deve permettere di implementare i metodi in modo efficiente

• Come si puo’ rappresentare?

• Analogo ad Intset con un Vector

• Differenza: occorrenze multiple di elementi

Page 21: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Attenzione

• Metodi insert e remove tolgono e aggiungono una occorrenza

• Metodo IsIn deve contare il numero delle occorrenze

• Metodi union e inter si puo’ sfruttare IsIn (piu’ efficiente)

Page 22: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Estensione

• Vogliamo estendere il tipo di dato IMultiSet (a posteriori) aggiungendo un operazione

(metodo d’istanza maxmul), che restituisce la molteplicita’ massima presente nell’insieme)

• Molteplicita’: numero occorrenze • Vogliamo una sottoclasse che aggiunge il

metodo

Page 23: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Problema

• La rappresentazione di Imultiset (comunque sia fatta) deve essere private

• Necessario per realizzare l’astrazione: mascherare l’implementazione

• Le sottoclassi (e analogamente tutti gli altri moduli) pero’ in questo modo non possono accedere alla rappresentazione

• Come si fa a fare maxmul???????

Page 24: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Rappresentazione Protected

• Se mettiamo la rappresentazione protected (invece che private) le sottoclassi possono accedere (non tutte le altre classi)

• Si perde l’astrazione verso le sottoclassi (il loro codice dipende dall’implementazione della superclasse)

• Si mantiene l’astrazione verso tutte le altre classi (il loro codice e’ per forza indipendente dall’implementazione della superclasse)

• Buon compromesso (rispetto ad usare public), ma vedremo come si puo’ fare meglio usando gli iteratori .)

Page 25: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Specifica della sottoclasse

public class Imultisetext extends IMultiset {//OVERVIEW: aggiunge un metodo

//metodi e costruttori public Imultisetext() {//EFFECTS: inizializza this al multiinsieme vuoto}

public int maxmul() {//EFFECTS: restituisce il massimo numero di occorrenze tra tutti gli elementi di this (0 se e’ vuoto)}

Page 26: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Soluzione

• Per avere una implementazione piu’ efficiente usiamo una rappresentazione particolare (invece di inserire gli elementi in modo “casuale” nel Vector)

• Usiamo un Vettore di coppie del tipo (elemento,n. occorrenze)

• Serve tipo ausiliario PairInt

Page 27: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

Idea della implementazione

• Tutte le informazioni su un certo elemento sono raggruppate insieme

• Esempio (7,3),(3,1),(1,3) rappresenta il multiinsieme {7,7,7,3,1,1,1}

• Nota che non vogliamo coppie diverse per lo stesso elemento tipo (1,2),(1,3). Una sola coppia deve descrivere l’elemento 1, tipo (1,5)

• Questa rappresentazione permette una implementazione piu’ efficiente dei metodi soprattutto quelli della sottoclasse

Page 28: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class PairInt {private int left;private int right;

public PairInt (int x,int y) {left=x;right=y;}

public int left() {return left; }

public int right() {return right;}

}

Page 29: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class IMultiset{protected Vector els;

public IMultiset () {els=new Vector();}

public int isin(int x) { for (int i=0; i<els.size(); i++) { PairInt q=(PairInt) els.elementAt(i); if (x==q.left()) { return q.right();}} return 0;}

public void insert(int x){if (isin(x)==0) { els.addElement(new PairInt(x,1)); return;} for (int i=0; i<els.size(); i++) { PairInt q=(PairInt) els.elementAt(i); if (x==q.left()) { int y=q.right(); y++; PairInt p=new PairInt(x,y); els.setElementAt(p,i); } } }

Page 30: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public void remove(int x){if (isin(x)==0) return; for (int i=0; i<els.size(); i++) { PairInt p=(PairInt) els.elementAt(i); if (x==p.left()) { int y= p.right(); y--; if (y>0) els.setElementAt(new PairInt(x,y),i); else els.removeElementAt(i); } }

}

public String toString () {String s="{" ;for (int j=0; j< els.size();j++){PairInt x=(PairInt) els.elementAt(j);for (int i=0; i< x.right();i++){s=s + x.left() + ",";}}s =s + "}";return s;}

}

Page 31: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public class ExtMul extends IMultiset{

public ExtMul () {}

public int maxmul() {int max=0;

for (int j=0; j< els.size();j++){PairInt x=(PairInt) els.elementAt(j);if (x.right() > max) {max=x.right();}}return max;}

}

}

Page 32: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.

public void inter(IMultiset x){for (int i=0; i<els.size(); i++) { PairInt p=(PairInt) els.elementAt(i); int num=x.isin(p.left()); if (num ==0) {els.removeElementAt(i);} else {if (num < p.right()) {els.setElementAt(new PairInt(p.left(),num),i);}}}}

public void union ( IMultiset x){for (int i=0; i<x.els.size(); i++) { PairInt p=(PairInt) x.els.elementAt(i); if (isin(p.left()) ==0) {els.addElement(p);} else {for (int j=0; j<els.size(); j++) { PairInt q=(PairInt) els.elementAt(j); if (q.left()==p.left()) { els.setElementAt(new PairInt(p.left(),q.right()+p.right()),i);}}}}}

}

Page 33: LIP: 19 Aprile 2005. Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.