Liste di Interi Esercitazione Int List Lista di

  • Slides: 24
Download presentation
Liste di Interi Esercitazione

Liste di Interi Esercitazione

Int. List • Lista di interi • Una lista è una disposizione ordinata di

Int. List • Lista di interi • Una lista è una disposizione ordinata di elementi ( non in modo crescente-descrescente, ma per ordine di inserimento) • Vediamo la specifica

Specifica di Int. List public class Int. List { // OVERVIEW: un Int. List

Specifica di Int. List public class Int. List { // OVERVIEW: un Int. List è una lista modificabile // di Integers. // Elemento tipico [x 1, . . . , xn] public Int. List () { // EFFECTS: inizializza this alla lista vuota } public Int. List (Integer x) { // EFFECTS: inizializza this alla lista che // contiene esattamente x }

Specifica di Int. List public void add. El (Integer x) { // EFFECTS: aggiunge

Specifica di Int. List public void add. El (Integer x) { // EFFECTS: aggiunge x all’inizio di this } public Integer first () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, altrimenti // ritorna il primo elemento di this} public Int. List rest () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva // Empty. Exception, altrimenti // ritorna la lista ottenuta da this togliendo // il primo elemento}

Specifica di Int. List public Int. List rest () throws Empty. Exception{ // EFFECTS:

Specifica di Int. List public Int. List rest () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva // Empty. Exception, altrimenti // ritorna la lista ottenuta da this togliendo // il primo elemento} public int size () { // EFFECTS: ritorna il numero di elementi di // this} public Iterator elements () { // EFFECTS: ritorna un generatore che produrrà // tutti gli elementi di this (come Integers) // nell’ordine che hanno in this }

Specifica di Int. List public boolean equals (Int. List o) { // EFFECTS: metodo

Specifica di Int. List public boolean equals (Int. List o) { // EFFECTS: metodo overridden, verifica se o e // this rappresentano la stessa lista public boolean rep. Ok (){// EFFECTS: standard} public String to. String (){// EFFECTS: standard } } • Dobbiamo riscrivere il metodo equals (di Object), dato che il tipo di dato e’ modificabile vogliamo vedere se hanno gli stessi elementi (altrimenti verificherebbe solo il puntatore)

Implementazione • • E` modificabile Bisogna mantenere l’ordinamento Vector? Facciamo invece vedere una implementazione

Implementazione • • E` modificabile Bisogna mantenere l’ordinamento Vector? Facciamo invece vedere una implementazione ricorsiva: lista concatenata • E` una delle strutture dati fondamentali in Informatica, essenziale per esempio in linguaggi che non hanno come primitivo un tipo di dimensione variabile quale Vector

Lista concatenata • o è vuota • o contiene un valore (di tipo Integer

Lista concatenata • o è vuota • o contiene un valore (di tipo Integer in questo caso) e un puntatore al resto della lista • Nota: si può implementare in modo ricorsivo • simile all’ albero binario (più semplice)

Rappresentazione public class Int. List { // OVERVIEW: un Int. List è una lista

Rappresentazione public class Int. List { // OVERVIEW: un Int. List è una lista non modificabile di Integers. // Elemento tipico [x 1, . . . , xn] private boolean vuota; private Integer val; private Int. List next; private int sz; Nota: la variabile sz mantiene il numero di elementi della lista, non è necessaria ma rende l’implementazione piu’ efficiente (va pero’ tenuta aggiornata)

Esercizio • Scrivere l’invariante di rappresentazione e la funzione di astrazione (riflettendo le scelte

Esercizio • Scrivere l’invariante di rappresentazione e la funzione di astrazione (riflettendo le scelte di progetto) • Implementare i metodi

Invariante (ricorsiva) I(c) = c. vuota oppure (c. next != null e I(c. next)

Invariante (ricorsiva) I(c) = c. vuota oppure (c. next != null e I(c. next) e c. sz= 1 + c. next. size() ) • O e’vuota (non c’è nessuna condizione) • Oppure il next deve essere definito • Il valore di sz deve essere uguale al numero di elementi del next +1

Funzione di astrazione a(c) = se c. vuota allora [], altrimenti a(c) = [c.

Funzione di astrazione a(c) = se c. vuota allora [], altrimenti a(c) = [c. val] + a(c. next) 4 Mappa gli oggetti concreti, implementati con una lista concatenata nella corrispondente lista, del tipo [x 1, . . . , xn] 4 La funzione di astrazione ricorsiva riflette il fatto che l’ordinamento implementato è di fatto quello astratto, il primo elemento è quello contenuto in val, poi seguono gli elementi del next

Costruttori public Int. List () { // EFFECTS: inizializza this alla lista vuota=true; sz=0;

Costruttori public Int. List () { // EFFECTS: inizializza this alla lista vuota=true; sz=0; } public Int. List (Integer x) { // EFFECTS: inizializza this alla lista che // contiene esattamente x vuota=false; val=x; next=new Int. List(); sz=1; }

Inserimento public void add. El (Integer x) { // EFFECTS: aggiunge x all’inizio di

Inserimento public void add. El (Integer x) { // EFFECTS: aggiunge x all’inizio di this Int. List n = new Int. List(x); n. next = this; n. sz = this. sz + 1; this =n; } 4 Mettiamo l’elemento in testa, creando una lista che contiene x 4 Corretto: a(c_pre) =L a(c) =[c. val] + a(c. next)=[x]+L

First e rest public Integer first () throws Empty. Exception{ // EFFECTS: se this

First e rest public Integer first () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception // altrimenti ritorna il primo elemento di this if (vuota) throw new Empty. Exception(“Int. List. first”); return val; } public Int. List rest () throws Empty. Exception{ // EFFECTS: se this è vuoto solleva Empty. Exception, // altrimenti ritorna la lista ottenuta da this // togliendo il primo elemento if (vuota) throw new Empty. Exception(“Int. List. first”); return next; }

Size public int size () { // EFFECTS: ritorna il numero di elementi di

Size public int size () { // EFFECTS: ritorna il numero di elementi di this return sz; } 4 Corretto: l’invariante assicura che sz contenga proprio il numero di elementi della lista Più efficiente: altrimenti dovrei usare un metodo ricorsivo per calcolarli

Equals public boolean equals (Int. List o) { // EFFECTS: metodo overridden, verifica se

Equals public boolean equals (Int. List o) { // EFFECTS: metodo overridden, verifica se o e this rappresentano la stessa lista if (vuota && o. vuota) {return true; } if (val != o. val) {return false; } return this. next. equals(o. next); } 4 Deve verificare che a(this) = a(o) 4 Si sfrutta il fatto che, come garantito dall’invariante, se non vale 4 vuota, allora next è definito (al limite è la lista vuota)

Commenti • Notate che come anche garantito dall’invariante, quando la lista non è vuota,

Commenti • Notate che come anche garantito dall’invariante, quando la lista non è vuota, next è definito (non null) • Questo garantisce che le chiamate ricorsive (p. e. equals) non sollevino eccezioni • Inoltre l’uso di vuota semplifica la definizione del caso base dell’induzione (lista vuota)

Iteratore public Iterator elements () { // EFFECTS: ritorna un generatore che produrrà tutti

Iteratore public Iterator elements () { // EFFECTS: ritorna un generatore che produrrà tutti // gli elementi di this (come Integers) nell’ordine che // hanno in this return new Int. List. Gen(this); } • Restituisce un generatore, istanza di un sottotipo di Iterator • Intlist. Gen è una classe interna di Int. List privata e statica (indipendente dagli oggetti)

Generatore • Dobbiamo generare tutti gli elementi della lista dal primo all’ultimo • Generatore:

Generatore • Dobbiamo generare tutti gli elementi della lista dal primo all’ultimo • Generatore: deve essere ricorsivo • Per iterare su l: prima generiamo l. val • Poi, chiamiamo il generatore di next

Implementazione • Usiamo una variabile figlio di tipo Int. List per memorizzare il generatore

Implementazione • Usiamo una variabile figlio di tipo Int. List per memorizzare il generatore del next • Usiamo una variabile corrente per sapere quando dobbiamo ancora generare val o quando dobbiamo chiamare il generatore di next

public class Int. List { private static class Int. List. Gen implements Iterator {

public class Int. List { private static class Int. List. Gen implements Iterator { private boolean corrente; private Int. List. Gen figlio; // sottogeneratore del resto della lista private Int. List me; // la lista da generare 4 si noti l’uso di me per memorizzare la lista su cui iteriamo

Metodi public Int. List. Gen(Int. List o) { // REQUIRES: o != null me=o;

Metodi public Int. List. Gen(Int. List o) { // REQUIRES: o != null me=o; if (o. sz >0) {corrente = true; figlio = new Int. List. Gen(o. next); }} public boolean has. Next () { if (me. vuota) {return false; } if (corrente) {return true; } return figlio. hasnext(); }

Metodi public Object next() throws No. Such. Element. Exception{ if (me. vuota) throw No.

Metodi public Object next() throws No. Such. Element. Exception{ if (me. vuota) throw No. Such. Element. Exception(“Int. List. elements”); if (corrente) {return me. val; corrente=false; } return figlio. next(); }