Liste Concatenate
11 Aprile 2008
•E’ una delle strutture dati fondamentali in tutti i
linguaggi di programmazione di alto livello
•Una Lista Concatenata serve per rappresentare
sequenze di elementi (di dimensione variabile)
[ 19,
57,
3,
35, 11,
91,
5 ]
[]
•Tipo di dato basato su una definizione RICORSIVA
Definizione Ricorsiva
• Una lista concatenata e’
• vuota
• o e’ un nodo che contiene un valore e un
riferimento ad una lista (il resto della lista)
Esempio
val next
Lista non vuota:
Primo elemento
11
64
Lista vuota
IntList
• Vediamo per esempio una possibile
specifica nel caso di elementi di tipo Integer
• Definiamo un tipo di dato astratto
modificabile
• Operazioni per
--costruire la lista vuota
--costruire un nodo
--aggiungere un elemento all’inizio
--metodi per scorrere i nodi della lista
Specifica di IntList
public class IntList {
// OVERVIEW: un IntList è una lista modificabile
// di Integer.
// Elemento tipico [x1,...,xn]
public IntList () {
// EFFECTS: inizializza this alla lista vuota }
public IntList (Integer x) throws
NullPointerException {
// EFFECTS: se x e’ null solleva
//NullPointerException, inizializza this alla
//lista che contiene esattamente x }
Specifica di IntList
public
void addEl (Integer x)
throws NullPointerException
{//MODIFIES:this
// EFFECTS: se x e’ null solleva
//NullPointerException, altrimenti aggiunge x
//all’inizio di this }
public Integer first () throws EmptyException{
// EFFECTS: se this è vuoto solleva
//EmptyException, altrimenti
// ritorna il primo elemento di this}
public IntList rest () throws EmptyException{
// EFFECTS: se this è vuoto solleva
//EmptyException, altrimenti
// ritorna la lista ottenuta da this togliendo
//il primo elemento}
Specifica di IntList
public int size () {
// EFFECTS: ritorna il numero di elementi di
//this}
public String toString (){
//EFFECTS: restituisce una stringa che descrive
//la sequenza di elementi di this }
}
}
Esempio sull’uso delle Liste
IntList p = new IntList ();
\\[]
p.addEl(new Integer(3));
\\[3]
p.addEl(new Integer(4));
\\[4,3]
p.addEl(new Integer(7));
\\[7,4,3]
•Il metodo toString() permette al solito di
osservare lo stato interno
Esempio sull’uso delle Liste
IntList p = new IntList (new
Integer(3));
\\[3]
p.addEl(new Integer(4));
\\[4,3]
p.addEl(new Integer(7));
\\[7,4,3]
•Il secondo costruttore che costruisce la lista di un
elemento non e’ necessario
Nota
•Il metodo rest restituisce il resto della lista
(la lista ottenuta rimuovendo il primo elemento)
•Il metodo first restituisce il primo elemento
IntList p = new IntList (new Integer(3));
p.addEl(new Integer(4));
p.addEl(new Integer(7));
• first=====> 7
•rest ====> restituisce la lista [4,3]
Scorrere la lista
•Usando first e rest si puo’ scorrere la lista (metodo di ricerca)
•Realizzato in un modulo separato in base alla specifica di
IntList
public static boolean cerca (Intlist l,Integer x)
throws NullPointerException{
// EFFECTS: se l o x sono null solleva
//NullPointerException,
//altrimenti restituisce true se x occorre nella
//lista l, false se non occorre}
Utilizzando solo la specifica
public static boolean cerca (Intlist l,Integer x)
throws NullPointerException{
if (x==null|| l==null) throw new
NullPointerException(“Lista.cerca”);
//caso base
if (l.size()==0) {return false;}
//caso ricorsivo
{Integer el=l.first();
if (el.equals(x)) {return true;}
return cerca(l.rest(),x);}
}
Esempio 1
•
•
•
•
•
l=[1,6,3] x=6
Confronta x con l.first()=1
Chiama la procedura con l’=l.rest()= [6,3] ed x=6
Confronta x con l’.first()=6
La chiamata ricorsiva restituisce true (il metodo
chiamante restituisce true)
Esempio 2
•
•
•
•
•
•
•
•
l=[1,6,3] x=4
Confronta x con l.first()=1
Chiama la procedura con l’=l.rest()= [6,3] ed x=4
Confronta x con l’.first()=6
Chiama la procedura con l’’=l’.rest()= [3] ed x=4
Confronta x con l’’.first()=3
Chiama la procedura con l’’’=l’’.rest()= [] ed x=4
Caso Base: lista vuota termina restituendo false
(tutti i metodi annidati restituiscono false)
Come si implementa?
• Ci sono vari modi (a LSD altre soluzioni)
• Dobbiamo scegliere delle variabili d’istanza che
permettano di rappresentare sia la lista vuota che
quella non vuota
• Deve essere possibile distinguere i due casi in
modo chiaro
private boolean vuota;
private Integer val;
private IntList next;
//indica se e’ vuota
//contiene il valore
//puntatore al resto
Rappresentazione Lista
val
next
vuota
Lista vuota:
Lista non vuota:
any
any
154
24
any
any
true
false
false
true
Nota
• Il flag vuota serve per indicare la lista vuota
• Nell’implementazione che facciamo quando
vuota e’ falso garantiamo che il puntatore al
resto della lista non sia null
• Semplifica l’implementazione dei metodi
ricorsivi (non sono necessari test per vedere
che il puntatore sia definito)
Implementazione
public class IntList {
// OVERVIEW: un IntList è una lista non modifica
// Integers.Elemento tipico [x1,...,xn]
private boolean vuota;
private Integer val;
private IntList next;
Costruttori
public IntList () {
// EFFECTS: inizializza this alla lista vuota
vuota=true;}
public IntList (Integer x) {
// EFFECTS: inizializza this alla lista che
contiene esattamente x
if (x==null) throw new
NullPointerException(“IntList.IntList”);
vuota=false; val=x; next=new IntList();}
Notate che nel secondo costruttore next viene inizializzato alla lista
vuota (sta sempre alla fine, definizione ricorsiva) !
Costruttori
val
next
vuota
Lista vuota:
Lista con un elemento:
any
any
24
any
any
true
false
true
Inserimento
public void addEl (Integer x) {
//MODIFIES:this
// EFFECTS: aggiunge x all’inizio di this
if (x==null) throw new
NullPointerException(“IntList.IntList”);
{if (vuota) {val=x;next=new IntList();vuota=false;}
else
{IntList n = new IntList(val);
n.next = this.next; //copia di this
this.val =x;
this.vuota=false;
this.next=n;}
}}
Mettiamo l’elemento in testa,
creando un nuovo nodo che contiene x ed ha come resto della lista this
First e rest
public Integer first () throws EmptyException{
// EFFECTS: se this è vuoto solleva EmptyException
//altrimenti ritorna il primo elemento di this
if (vuota) throw new
EmptyException(“IntList.first”);
return val;}
public IntList rest () throws EmptyException{
// EFFECTS: se this è vuoto solleva EmptyException,
//altrimenti ritorna la lista ottenuta da this
//togliendo il primo elemento
if (vuota) throw new
EmptyException(“IntList.first”);
return next;}
Size
public int size () {
// EFFECTS: ritorna il numero di elementi di this
if (vuota) return 0;
return 1 + next.size();
}
Metodo
Ricorsivo!!!!!!!!!
ToString()
public String toString (){
String s=“”;
if (vuota) {return s;}
return val.intValue() + next.toString();
}
Metodo Ricorsivo !
Esercizio I
• Definire una variante StringList
• Contiene Stringhe
• Ha un metodo per aggiungere all’inizio ed alla
fine,e per rimuovere
• Ha un metodo per verificare l’uguaglianza di due
liste
Specifica di StringList
public class StringList {
// OVERVIEW: un StringList è una lista
//modificabile di stringhe.
// Elemento tipico [x1,...,xn]
public StringList () {
// EFFECTS: inizializza this alla lista vuota }
public StringList (String x) {
// EFFECTS: se x e’ null solleva
//NullPointerException, altrimenti inizializza
//this alla lista che contiene esattamente x }
Specifica di StringList
public void FaddEl (String x) {
//MODIFIES:this
// EFFECTS: se x e’ null solleva
//NullPointerexception, altrimenti aggiunge x
//all’inizio di this }
public void LaddEl (String x) {
//MODIFIES:this
// EFFECTS: se x e’ null solleva
//NullPointerexception, altrimenti aggiunge x
//alla fine di this }
public void remove (String x) {
//MODIFIES:this
// EFFECTS: se x e’ null solleva
//NullPointerexception, altrimenti rimuove da
//this una occorrenza di x }
Specifica di StringList
public String first () throws EmptyException{
// EFFECTS: se this è vuoto solleva
//EmptyException, altrimenti
// ritorna il primo elemento di this}
public StringList rest () throws EmptyException{
// EFFECTS: se this è vuoto solleva
//EmptyException, altrimenti
// ritorna la lista ottenuta da this togliendo
//il primo elemento}
Specifica di StringList
public int size () {
// EFFECTS: ritorna il numero di elementi di
//this}
public boolean equals(Object x) {
// EFFECTS: se x e’ null solleva
//NullpointerException, se this ed x sono uguali
//(sono liste che rappresentano la stessa
//sequenza di elementi) restituisce
//true, altrimenti false}
public String toString (){// EFFECTS: standard }
}
}
Esercizio II
• Implementare la seguente classe
• Classe che definisce alcune procedure
statiche per manipolare liste di stringhe
• Da realizzare in modulo separato (non
vedono la rappresentazione della lista)
• metodi ricorsivi
public class IntListProc {
// OVERVIEW: fornisce metodi statici per manipolare
//liste di stringhe
public static String min(StringList l) throws
EmptyException
{// REQUIRES: l non e’ null
//EFFECTS: se l e’ vuota solleva EmptyException,
altrimenti restituisce il minimo elemento di l}
public
static StringList
append (StringList l1, StringList l2)
{// REQUIRES: l1 ed l2 non null
//EFFECTS: restituisce una lista che e’ la
//concatenazione di l1 ed l2. Ex: l1=[8,0], l2=[9]
===> [8,0,9]
}
}
ATTENZIONE: le liste passate per parametro non devono
essere modificate
MAIN
• Test della definizione di StringList (usare
toString())
• Test dei metodi statici
Metodi Statici
• Devono operare su StringList tramite
l’interfaccia pubblica
• Non hanno visibilita’ delle variabili
d’istanza val e next
Scarica

Lucidi