Pilecode
Pilecode
PILE E CODE
.. Le pile
In una struttura di
questo tipo i dati (i libri)
vengono inseriti solo in
cima e possono essere
estratti solo dalla cima.
.. Le pile
7
6
5
top = 0 → pila vuota 4
3
top = max → pila piena
2
top 7
1
.. Le pile
public class Pila
{ private int top;
private final int MAXX;
private int elem[];
private static final int MAXDEFAULT = 10;
public Pila()
{ this(MAXDEFAULT);
}
Regola 2: appena si incontra una parentesi chiusa in a, si fa pop di un operatore dallo stack b e si
fa il pop di tutti gli operandi richiesti da tale operatore estraendoli dallo stack c (taluni
operatori potrebbero essere unari).
Operatore e operandi vengono usati per ottenere un nuovo valore che viene pushed nello stack c.
.. Simulazione 2
Si riapplica la regola 2:
abbiamo una parentesi
chiusa, dobbiamo fare pop
di *, 10 e 3.
Il risultato è pushed in c.
7
) * 3 21
a b c a b c
INFISSA
5*(((9+8) * (4*6)) +7)
POSTFISSA
598+46**7+*
ES: INFISSA B*C POSTFISSA BC*
INFISSA A+B*C POSTFISSA ABC*+
PREFISSA o POLACCA
ES: INFISSA B*C PREFISSA *BC
INFISSA A+B*C PREFISSA +A*BC
.. Le espressioni aritmetiche
INFISSA
5*(((9+8) * (4*6)) +7)
POSTFISSA
5 9 8 + 4 6 * * 7 + * // NON C’E’ BISOGNO DI PARENTESI basta
sostituire ogni occorrenza di ab* con (a*b), di ab+ con (a+b)
5 (9+8) (4*6) * 7 + *
5 ((9+8) * (4*6) ) 7 + *
5 ( ((9+8) * (4*6) ) + 7 ) *
(5 * ( ((9+8) * (4*6) ) + 7 ) )
.. Valutazione di un’espressione postfissa
if (a[i]==‘+’)
s.push(s.pop()+s.pop());
if(a[i]==‘*’)
s.push(s.pop()*s.pop());
//leggi fino al prossimo spazio
//converti la stringa letta in un intero val
s.push(val);
}
Out.println(s.pop()+ “ ”);
}
}
.. Conversione da forma infissa a forma postfissa
class Stack
{
private Object[] s;
private int N;
stack(int maxN)
{ s=new Object[maxN]; N=0; }
boolean isEmpty()
{ return (N == 0); }
void push(Object item)
{s[N++] = item;}
Object pop()
{Object t = s[--N]; s[N] = null; return t;}
}
.. Stack generico
Limiti:
1. Per inserire tipi primitivi es. interi dobbiamo impiegare classi
wapper come Integer
s.push(new Integer(x))
((Integer) s.pop()).intValue()
2. Si ci espone ad errori in running time dovuti ad una sbagliata
conversione dei tipi
CODE
.. Le code
Gli stack realizzano una “strategia” First In First Out.
Tale “strategia” possiede una ovvia alternativa, spesso usata in
molte situazioni della vita quotidiana (prenotazioni, posta, etc)
Una struttura dati di questo tipo prende il nome di Coda o
Sistema FIFO (First In First Out).
Dal punto di vista ADT una CODA o QUEUE (leggi “chiù”) è una
sequenza di elementi che può essere “accorciata” da un lato e
allungata da un altro lato:
Dequeue: operazione Enqueue: operazione
che corrisponde alla che corrisponde
estrazione di un elemento all’inserimento di un
dalla coda elemento dalla coda
exit ingresso
.. Le code
Dal punto di vista astratto per la struttura coda (queue)
le operazioni “base” sono le seguenti:
inserire un elemento x in coda (EnQueue(x));
togliere un elemento dalla coda (DeQueue());
verificare se la coda è vuota (IsEmpty());
cancellare tutti i dati (ClearQueue());
leggere (senza toglierlo dalla coda) il primo elemento in
attesa (readHead());
nel caso in cui si preveda una coda con capacità massima
limitata verificare se la coda ha raggiunto la sua massima
capacità: (IsFull()).
.. Code: implementazione con array
Gli array sono il supporto più naturale che viene in mente dovendo
gestire una “sequenza”. Essi purtroppo presentano numerosi
problemi nel momento in cui debbono gestire le operazioni tipiche di
una coda.
1 4 8 3 2 6 9
1 4 8 3 2 6 9 Posizione libera= 7
(queue full)
Dequeue
8 3 2 6 9 Posizione libera= 4
Posizione libera= 4
Enqueue 7 3 2 6 9 7
Posizione libera= 5
3 2 6 9 7
.. Le code circolari
Tuttavia eseguire uno shift di tutti gli elementi dopo ogni
estrazione è troppo oneroso.
Per tale motivo è stata pensata una struttura,
denominata coda circolare, nella quale esistono due indici,
head e tail, che indicano il primo elemento e l’ultimo.
head
3
2
9 4
5 1
3 8
tail
.. Le code circolari
head
3
tail
2
9 4
5 1
3 8
head
tail
2 3
9 4
5 1
3 8
.. Le code circolari
head
tail
2
9 4
5 1
3 8
head
tail
7 2
7 9 4
5 1
3 8
.. Le code circolari
head
tail
2
9 4
5 1
3 8
head
tail
2
9 4
5 1
3 8 head
tail
3 5 9 2 4 1 8
Piccola nota:
Sia A l’array di supporto e sia DIM=A.length;
tail head
tail
head
.. Le code circolari
Se però i due puntatori coincidono, dobbiamo poter
distinguere le condizioni di coda vuota o coda con un solo
elemento.
head
tail
tail
head x
.. Le code circolari
x x
x
x x
x x
x x
x x
x x x x
.. Le code circolari
Nel secondo caso la head punta alla prima posizione piena
e tail punta all’ultima piena (tranne se la coda è vuota).
In tal caso se gli indici si sovrappongono la coda può
essere vuota o con un solo elemento. Tramite una variabile
booleana (necessaria) si possono distinguere i due casi.
tail tail
head head
Empty = true Empty = false
x
.. Le code circolari
Nella seguente implementazione prenderemo in esame il
primo caso.
public class Queue
{ private int head, tail;
private final int MAX;
private int elem[];
private static final int MAXDEFAULT = 10;
public Queue()
{ this(MAXDEFAULT);
}
public Stack( )
{ this( MAXDEFAULT );
}
public Stack( int max )
{ MAX = max;
elem = new Object[ MAX ];
top = 0;
}
.. Le pile : metodi con eccezioni
public Object topElem( )
{
if( isEmpty( ) )
return null;
return elem[ top ];
}
.. Le pile : metodi con eccezioni
public Object pop( ) throws Underflow
{
if( isEmpty( ) )
throw new Underflow( );
return elem[ --top ];
}
public void push( Object x ) throws Overflow
{
if( isFull( ) )
throw new Overflow( );
elem[ top++ ] = x;
}
.. Le pile : metodi con eccezioni
public class Overflow extends Exception
{
}
pop-push
public Queue( )
{
this( MAXDEFAULT );
}
try
{
for( int i = 0; i < 10; i++ )
q.enqueue( new Integer( i ) );
}
catch( Overflow e ) { System.out.println( "Unexpected overflow" ); }
while( !q.isEmpty( ) )
try
{
System.out.println( q.dequeue( ) );
}
catch( Underflow e ) { System.out.println( "Unexpected underflow" ); }
}
..
Esercizio
Invertire l'ordine degli elementi di una pila S usando una
coda Q.
.. Esercizio
public class Ex1 {
while( !S.isEmpty( ) )
Q.enqueue(S.pop());
while( !Q.isEmpty( ) )
S.push( Q.dequeue( ) );
return;
}
.. Esercizio
public static void main (String[] args) {
//Testiamo il funzionamento del metodo reverseStack su
uno stack di elementi di tipo intero
try
{
for( int i = 0; i < 10; i++ )
S.push( new Integer( i ) );
}
catch( Overflow e ) {System.out.println(
"Unexpected overflow" ); }
S.printStack();
System.out.println("\nSize Stack = "+ S.getSize() );
.. Esercizio
……
try
{
reverseStack(S);
}
catch( Overflow e ) { System.out.println(
"Unexpected overflow" ); }
catch( Underflow e ) {System.out.println(
"Unexpected underflow" ); }
S.printStack();
System.out.println("\nSize Stack = "+ S.getSize() );
}
.. Implementazione delle CODE in struttura dinamica
Esercizio
Trasferire gli elementi di una pila S1 in una pila S2 in
modo che gli elementi di S2 risultino avere lo stesso
ordinamento che avevano in S1 (usare una terza pila di
supporto).
.. Esercizio
public class Ex2 {
public static void transferStack (Stack S1, Stack S2) throws
Overflow,Underflow
{
//Stack S3 di appoggio
while( !S1.isEmpty( ) )
S3.push(S1.pop());
while( !S3.isEmpty( ) )
S2.push(S3.pop());
}
.. Esercizio
public static void main (String[] args) {
try
{
for( int i = 0; i < 10; i++ )
S1.push( new Integer( i ) );
}
catch( Overflow e ) {System.out.println("Unexpected overflow" ); }
}
}
.. Conversione tra basi di numerazione
do
{
b= b + ((Integer) S.pop()).toString();
} while(!S.isEmpty());
return b;
}
.. Addizione di numeri molto grandi