La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

1 Un esempio: le liste ordinate di interi. 2 Liste ordinate  OrderedIntList 4 lista ordinata di interi –modificabile.

Presentazioni simili


Presentazione sul tema: "1 Un esempio: le liste ordinate di interi. 2 Liste ordinate  OrderedIntList 4 lista ordinata di interi –modificabile."— Transcript della presentazione:

1 1 Un esempio: le liste ordinate di interi

2 2 Liste ordinate  OrderedIntList 4 lista ordinata di interi –modificabile

3 3 Specifica di OrderedIntList 1 public class OrderedIntList { // OVERVIEW: una OrderedIntList è una lista // modificabile di interi ordinata // tipico elemento: [x1,..., xn], xi

4 4 Specifica di OrderedIntList 2 public boolean isIn (int el) // EFFECTS: se el appartiene a this ritorna // true, altrimenti false public boolean isEmpty () // EFFECTS: se this è vuoto ritorna true, altrimenti // false public int least () throws EmptyException // EFFECTS: se this è vuoto solleva EmptyException // altrimenti ritorna l’elemento minimo in this public boolean repOk () public String toString () // metodi test standard }

5 5 Specifica di OrderedIntList 3 public class OrderedIntList { public OrderedIntList () public void addEl (int el) throws DuplicateException public void remEl (int el) throws NotFoundException public boolean isIn (int el) public boolean isEmpty () public int least () throws EmptyException public boolean repOk () public String toString ()}  DuplicateException e NotFoundException checked

6 6 Come implementarla? 4 Potremmo usare una struttura dati lineare: lista concatenata 4 lista concatenata: definizione ricorsiva 4 o e’ vuota 4 o e’ formata da un nodo, che contiene un valore (di tipo int) ed un puntatore al resto della lista 4 bisognerebbe mantenere i nodi ordinati in base al valore associato in ordine crescente (tipo esercizio di LIP)

7 7 Usiamo invece un albero binario 4 albero binario: struttura ricorsiva tipo lista 4 o e’ vuoto 4 o contiene un nodo (detto radice) a cui e’ associato un valore (in questo caso di tipo int) ed un puntatore a due alberi, detti sottoalbero sinistro e destro rispettivamente 4 Nota: si chiama binario esattamente perche’ ogni nodo ha due figli (si puo’ generalizzare)

8 8 Esempio I nodi che puntano a sottoalberi vuoti si dicono foglie 4 Il nodo radice contiene 4

9 9 Commenti 4 Rispetto ai tipi di dato lineari, lista doppia –si può percorrere da ogni elemento in avanti o all’indietro 4 Mediamente piu’ efficiente la ricerca se i valori sono inseriti in modo opportuno 4 Complessita’ degli algoritmi di inserimento, ricerca, eliminazione etc… (LSD, Algoritimica)

10 10 Ordinamento 4 Per mantenere l’ordinamento richiediamo che, per ogni nodo a cui e’ associato n 4 tutti i valori contenuti nel sottoalbero sinistro abbiano valore strettamente minore di n, 4 tutti i valori contenuti nel sottoalbero destro abbiano valore strettamente maggiore di n.

11 11 Vantaggio 4 Se leggiamo i valori effettuando la visita dell’albero in ordine simmetrico otteniamo I valori ordinati in modo crescente 4 visita simmetrica: in modo ricorsivo, visitiamo prima il sottoalbero sinistro, poi la radice, poi il sottoalbero destro 4 Un esempio

12 12 Come lo implementiamo? public class OrderedIntList { // OVERVIEW: una OrderedIntList è una lista // modificabile di interi ordinata // tipico elemento: [x1,..., xn], xi

13 13 Come è fatta ?  La lista vuota ha la variabile boolean true  Le foglie puntano alla lista vuota  Notate l’ordinamento 12F F 4 F FF T TF T T T T T

14 14 Commenti 4 L’invariante di rappresentazione e la funzione di astrazione descrivono le caratteristiche dell’implementazione che abbiamo in mente 4 Dipendono dalla rappresentazione e devono essere inserite come commenti alla rappresentazione 4 Sono fondamentali per ragionare sulla correttezza dell’implementazione o per capire l’implementazione (se per esempio qualcuno la dovesse modificare)

15 15 private boolean vuota; private OrderedIntList prima, dopo; private int val; I(c) = c.vuota oppure (c.prima != null e c.dopo != null e I (c.prima) e I (c.dopo) e (!c.prima.isEmpty() -> c.prima.max() < c.val) e (!c.dopo.isEmpty() -> c.dopo.least() > c.val) ) 4 l’invariante esprime le proprieta’ che devono soddisfare gli oggetti concreti, ovvero le loro variabili d’istanza 4 In questo caso il ruolo di vuota e la relazione tra i valori contenuti nella radice e nei sottoalberi (necessarie per garantire l’ordinamento richiesto) Invariante

16 16 private boolean vuota; private OrderedIntList prima, dopo; private int val;  (c) = se c.vuota allora [], altrimenti  (c) =  (c.prima) + [c.val] +  (c.dopo) 4 Mappa gli oggetti concreti, implementati con un albero binario, nella corrispondente lista ordinata in modo crescente, tipo [x1,..., xn], xi

17 17 Esempio 4 Oggetto concreto x quello della figura 4 Oggetto astratto corrispondente e’ la seguente lista   (x)= [4,5,12,17,19]

18 18 Nota 4 Oggetto concreto, implementato tramite un albero binario, non e’e non deve essere visibile a chi usa OrderedIntList  Oggetto astratto (  (this) ) e’ visibile tramite il metodo toString () che implementa la funzione di astrazione 4 Fondamentale se vogliamo conoscere lo stato dell’oggetto su cui stiamo lavorando, pur non avendo accesso diretto alla rappresentazione 4 Permette di fare delle verifiche sul comportamento dei metodi (creo un oggetto, inserisco dei valori, vedo se il risultato e’ quello atteso)

19 19 Domanda 4 Se abbiamo due implementazioni diverse (una fatta con l’albero binario e l’altra con una lista concatenata) 4 Diverse invarianti e f. di astrazione 4 Ma gli oggetti astratti devono essere dello stesso tipo, quello descritto nella OVERVIEW [x1,..., xn], xi

20 20 Esercizio 4 Fate l’implementazione con lista concatenata (tipo LIP) 4 Formalizzate la funzione di astrazione e l’invariante 4 Verificate che l’invariante valga 4 Verificate la correttezza dei metodi 4 Dal punto di vista di chi usa il tipo di dato non deve vedersi differenza

21 21  (c) =  (c.prima) + [5] +  (c.dopo) = ([]+  4]+[]) + [5] + ([]+  8]+[])= [4, 5, 8] 4 Funzione di astrazione per il sottoalbero con radice 5 4 Se l’oggetto concreto non soddisfa l’invariante (che impone l’ordinamento) pero’ non e’ detto che troviamo I valori ordinati nel modo richiesto 4 Facciamo vedere che l’invariante impone dei vincoli sufficienti a garantire le proprieta’ dei dati richieste nella specifica Esempio

22 22 4 Facciamo vedere per induzione sulla lunghezza della lista che Se I(c) allora  (c) =[x1,..., xn], xi

23 23  Caso Induttivo: non vale c.vuota, ma (c.prima != null e c.dopo != null e I (c.prima) e I (c.dopo) e (!c.prima.isEmpty() -> c.prima.max() < c.val) e (!c.dopo.isEmpty() -> c.dopo.least() > c.val) )  Abbiamo  (c) =  (c.prima) + [c.val] +  (c.dopo)= [y1,..., yn]+ [c.val] + [z1,..., zk]  Dato che c.prima che c.dopo sono piu’ piccole di c, e che soddisfano l’invariante, allora per ipotesi induttiva [y1,..., yn] e [z1,..., zk] sono ordinate in modo crescente 4 Le altre proprieta’ dell’invariante garantiscono che sia anche tutta ordinata Invariante

24 24 4 L’invariante cattura le proprieta’ richieste nella specifica dei dati, in particolare l’ordinamento degli interi crescente (l’abbiamo fatto vedere) 4 Rimangono da implemenatre i metodi in modo che preservino l’invariante 4 Discutiamo anche la loro correttezza rispetto alla specifica, assumendo che l’invariante valga, e utilizzando la funzione di astrazione per collegare la specifica che parla di oggetti astratti e l’implementazione che si riferisce agli oggetti concreti Invariante

25 25 Implementazione public class OrderedIntList { // OVERVIEW: una OrderedIntList è una lista // modificabile di interi ordinata // tipico elemento: [x1,..., xn], xi

26 26 Inserire e rimuovere 4 Difficili perche’ bisogna preservare l’ordinamento 4 Le proprieta’ dell’ordinamento sono espresse dall’invariante (ci aiuta a non fare errori in una situazione un po’ complessa) 4 Vediamo un esempio

27 27 public void addEl (int el) throws DuplicateException // MODIFIES: this // EFFECTS: aggiunge el a this, se el non occorre in // this, altrimenti solleva DuplicateException {if (vuota) { prima = new OrderedIntList(); dopo = new OrderedIntList(); val = el; vuota = false; return; } if (el == val) throw new DuplicateException(“OrderedIntList.addEl”); if (el < val) prima.addEl(el); else dopo.addEl(el); } 4 Ricorsiva, inserisce rispettando l’ordinamento 4 Propaga automaticamente l’eventuale eccezione sollevata dalle chiamate ricorsive Inserire un elemento

28 28 Esempio 4 vediamo la lista prodotta dalla sequenza di comandi OrderedIntList ls = new OrderedIntList(); ls.addEl(12); ls.addEl(5); ls.addEl(17); ls.addEl(4);ls.addEl(8); ls.addEl(19); 12F F 4 F FF T TF T T T T T

29 29 Invariante: per casi I(c) = c.vuota oppure (c.prima != null e c.dopo != null e I(c.prima) e I(c.dopo) e (!c.prima.isEmpty() -> c.prima.max() < c.val) e (!c.dopo.isEmpty() -> c.dopo.least() >= c.val) ) public void addEl (int el) throws DuplicateException {if (vuota) { prima = new OrderedIntList(); dopo = new OrderedIntList(); val = el; vuota = false; return; }... prima != null e dopo != null (calcolati dal costruttore) I (prima) e I (dopo) (calcolati dal costruttore) le implicazioni sono vere perché la premessa è falsa

30 30 Invariante: this non vuoto I(c) = c.vuota oppure (c.prima != null e c.dopo != null e I(c.prima) e I(c.dopo) e (!c.prima.isEmpty() -> c.prima.max() < c.val) e (!c.dopo.isEmpty() -> c.dopo.least() >= c.val) ) public void addEl (int el) throws DuplicateException... if (el < val) prima.addEl(el); else dopo.addEl(el); } 4 prima != null e dopo != null (this non e’ vuoto) I (prima) e I (dopo) (calcolati da una chiamata ricorsiva su una lista piu’ piccola)  ramo then: il nuovo massimo di prima è (induttivamente) minore di val  ramo else: il nuovo minimo di dopo è (induttivamente) maggiore di val

31 31 Specifica  (c) = se c.vuota allora [], altrimenti  (c.prima) + [c.val] +  (c.dopo) public void addEl (int el) throws DuplicateException // MODIFIES: this // EFFECTS: aggiunge el a this, se el non occorre in // this, altrimenti solleva DuplicateException {if (vuota) { prima = new OrderedIntList(); dopo = new OrderedIntList(); val = el; vuota = false; return; }...   (c pre ) = []   (c.prima) = [] e  (c.dopo) = [] e  c.val] = [el]   (c) = [el] (ha inserito l’elemento)

32 32 Specifica public class OrderedIntList { private boolean vuota; private OrderedIntList prima, dopo; private int val; //  (c) = se c.vuota allora [], altrimenti //  (c.prima) + [c.val] +  (c.dopo) public void addEl (int el) throws DuplicateException // MODIFIES: this // EFFECTS: aggiunge el a this, se el non occorre in // this, altrimenti solleva DuplicateException... if (el == val) throw new DuplicateException(“OrderedIntList.addEl”); 4 se ci sono elementi duplicati solleva l’eccezione, eventualmente propagando eccezioni sollevate dalle chiamate ricorsive (vedi dopo)

33 33 Specifica //  (c) = se c.vuota allora [], altrimenti //  (c.prima) + [c.val] +  (c.dopo) public void addEl (int el) throws DuplicateException // MODIFIES: this // EFFECTS: aggiunge el a this, se el non occorre in // this, altrimenti solleva DuplicateException... if (el < val) prima.addEl(el); else dopo.addEl(el); } 4  (c pre ) =  (c.prima pre ) + [c.val] +  (c.dopo pre )  se el < val la chiamata ricorsiva solleva l’eccezione oppure produce   (c.prima) = aggiunge el a prima pre 4  (c.dopo) =  (c.dopo pre ) 4  (c) = aggiunge el a c pre 4 Analogo nel caso simmetrico

34 34 Rimuovere un elemento 4 Difficile, bisogna mantenere l’ordinamento 4 Supponiamo di dovere rimuovere 12 (e’ la radice) 4 Non possiamo semplicemente spostare nella radice uno dei nodi figli (ex. 5)

35 35 Idea 4 si prende il valore minimo del dopo (se c’e’) e si mette al posto della radice (e si rimuove dal dopo) 4 e’ di sicuro piu’ grande di tutti i valori di prima e piu’ piccolo di quelli di dopo 4 se dopo e’ vuoto allora si ricopia nel nodo radice il sottoalbero prima 4 in questo modo viene preservato l’ordinamento imposto dall’ordinamento

36 36 Implementazione di OrderedIntList 5 public void remEl (int el) throws NotFoundException // MODIFIES: this // EFFECTS: toglie el da this, se el occorre in // this, altrimenti solleva NotFoundException {if (vuota) throw new NotFoundException(“OrderedIntList.remEl”); if (el == val) try { val = dopo.least(); dopo.remEl(val); } catch (EmptyException e) { vuota = prima.vuota; val = prima.val; dopo = prima.dopo; prima = prima.prima; return;} else if (el < val) prima.remEl(el); else dopo.remEl(el); }

37 37 Implementazione di OrderedIntList 6 public boolean isIn (int el) // EFFECTS: se el appartiene a this ritorna // true, altrimenti false {if (vuota) return false; if (el == val) return true; if (el < val) return prima.isIn(el); else return dopo.isIn(el); } public boolean isEmpty () // EFFECTS: se this è vuoto ritorna true, altrimenti false {return vuota; } Si ricerca in base all’ordinamento (efficiente, non si visita tutto)

38 38 Implementazione di OrderedIntList 6.1 public class OrderedIntList { private boolean vuota; private OrderedIntList prima, dopo; private int val; //  (c) = se c.vuota allora [], altrimenti //  (c.prima) + [c.val] +  (c.dopo) public boolean isIn (int el) // EFFECTS: se el appartiene a this ritorna // true, altrimenti false {if (vuota) return false; if (el == val) return true; if (el < val) return prima.isIn(el); else return dopo.isIn(el); } public boolean isEmpty () // EFFECTS: se this è vuoto ritorna true, altrimenti false {return vuota; } 4 dimostrazioni di correttezza ovvie, visto che l’invariante che garantisce l’ordinamento

39 39 Implementazione di OrderedIntList 7.1 public class OrderedIntList { private boolean vuota; private OrderedIntList prima, dopo; private int val; public int least () throws EmptyException // EFFECTS: se this è vuoto solleva EmptyException // altrimenti ritorna l’elemento minimo in this {if (vuota) throw new EmptyException(“OrderedIntList.least”); try { return prima.least(); } catch (EmptyException e) {return val;} } 4 dimostrazione di correttezza ovvia usando l’invariante, che garantisce l’ordinamento  Ritorna proprio il primo elemento di  (this)

40 40 Implementazione di OrderedIntList 7.1 public class OrderedIntList { private boolean vuota; private OrderedIntList prima, dopo; private int val; public String toString(){ // EFFECTS:standard {if (vuota) return “”; return prima.toString() + val + dopo.toString(); } } 4 dimostrazione di correttezza ovvia usando l’invariante, che garantisce l’ordinamento  Implementa  (this) visita in ordine simmetrico


Scaricare ppt "1 Un esempio: le liste ordinate di interi. 2 Liste ordinate  OrderedIntList 4 lista ordinata di interi –modificabile."

Presentazioni simili


Annunci Google