Applicazione dello stack: valutazione di espressioni aritmetiche

3/24/15
Uso dello stack nella
valutazione delle
espressioni aritmetiche
Corso: Strutture Dati
Docente: Annalisa De Bonis
Valutare le espressioni
aritmetiche
l 
Quando si valuta un’espressione aritmetica bisogna tener
conto dell’ordine di precedenza e dell’associatività degli
operatori
l 
l 
Qui consideriamo espressioni con operatori aritmetici associativi
a sinistra
Idea:
l 
Due stack:
l 
valStack per i valori
l 
opStack per gli operatori
§ 
Si fa il push di ogni operatore ma solo dopo aver estratto e
applicato tutti gli operatori con precedenza maggiore o
uguale
1
3/24/15
Algoritmo EvalExp()
Input: una stringa che rappresenta un’espressione aritmetica
Output: il valore dell’espressione
while c’è un altro carattere c da scandire
if c è un numero then valStack.push(c)
else
while( opStack non è vuoto ∧ precedenza( c ) ≤ precedenza(opStack.top()))
x ← valStk.pop(); //fino a che al top dello stack ci sono operatori con
y ← valStk.pop(); //priorità maggiore rispetto a c, si estrae il pop
op ← opStk.pop(); // di opStack e si applica l’operatore estratto ai
valStack.push( y op x ); // due operandi in cima a valStack
opStack.push( c )
while( opStack non è vuoto ) //alla fine si applicano gli operatori rimasti in opStack
x ← valStk.pop();
//agli operandi rimasti in vaStack
y ← valStk.pop();
op ← opStk.pop();
valStack.push( y op x );
return valStack.top();
Esempio
3 + 4 * 6 - 8
6
4
4
3
3
3
+
4
3
+
3
8
*
+
27
-
24
*
+
3
19
+
27
-
restituisce 19
2
3/24/15
Esempio
9 + 4 - 6 - 2
9
9
9
2
6
4
13
+
+
13
5
-
-
7
7
-
-
restituisce 5
Esercizio 1
l 
Se l’espressione è in notazione postfissa è
possibile valutarla usando un unico stack?
l 
Esempi di espressioni aritmetiche in notazione
postfissa
l  1 2 + 5 * corrisponde a ( 1 + 2 ) * 5
l  1 2 5 * + corrisponde a 1 + 2 * 5
3
3/24/15
01/03/12
Soluzione esercizio 1
l 
Soluzione esercizio 1
Usiamo uno stack per gli operandi
l 
l 
Usiamo
per gli un
operandi
Ogni
voltauno
chestack
incontriamo
operando facciamo il
! 
Ogni
volta
che
incontriamo
un
operando
push dell’operando
facciamo
il push
dell’operando
Ogni
volta che
incontriamo
un operatore
!  Ogni volta che incontriamo un operatore
1. preleviamo (con 2 operazioni di pop) 2
1. 
preleviamo (con 2 operazioni di pop) 2 operandi
operandi
dallo stack
dallo stack
! 
2.
Applichiamo l’operatore ai due operandi e facciamo il push
2.  Applichiamo l’operatore ai due operandi e facciamo il
del risultato
nello
stacknello stack
push del
risultato
Esempio:
6 2 * 4 + 2 6
Strutture Dati 2011-2012
A. De Bonis
6
/
6
2
6
+
12
4
12
16
2
16
2
16
8
16
2
Esercizio 2
Esercizio 2
E` possibile utilizzare un unico stack per
trasformareutilizzare
un’espressione
infissa
in per
E` possibile
un unico
stack
postfissa?
! 
l 
trasformare un’espressione infissa in
postfissa?
Strutture Dati 2011-2012
A. De Bonis
4
4
3/24/15
Soluzione esercizio 2
l 
Gli operandi compaiono nello stesso ordine in
cui comparivano nella postfissa
l 
l 
Di conseguenza non appena si incontra un operando
lo aggiungiamo alla stringa output
Gli operatori invece cambiano posizione in
quanto
1. 
2. 
devono seguire gli operandi
possono cambiare d’ordine a causa delle regole di
priorità e delle parentesi
Soluzione esercizio 2
l 
Idea: Usiamo uno stack per gestire i raggrupamenti
nelle parentesi e le precedenze degli operatori.
l  Quando incontriamo ‘(‘ facciamo il push della
parentesi nello stack.
l  Quando incontriamo ‘)’ facciamo il pop di tutti gli
operatori fino a che al top dello stack non compare
‘(‘. (Facciamo il pop anche di ‘(‘ ).
l  Man mano che estraiamo gli operatori dallo stack,
li inseriamo nella stringa output.
l  Quando incontriamo uno degli operatori +, -, /, *, lo
inseriamo nello stack dopo aver fatto il pop di tutti gli
operatori con priorità maggiore o uguale.
l  Man mano che estraiamo gli operatori dallo stack, li
inseriamo nella stringa output.
5
01/03/12
01/03/12
3/24/15
Soluzione
Soluzione esercizio
esercizio 2:
2: lo
lo
pseudocodice
Soluzione esercizio 2
pseudocodice
Input: stringa che rappresenta un’espressione aritmetica in notazione infissa
Input: stringa che rappresenta un’espressione aritmetica in notazione infissa
Output: stringa che rappresenta l’espressione input in notazione postfissa
Output: stringa che rappresenta l’espressione input in notazione postfissa
/* Lo pseudocodice assume che l’espressione sia ben formata*/
/* Lo pseudocodice assume che l’espressione sia ben formata*/
Crea una stringa vuota Postfix;
Crea una stringa vuota Postfix;
Crea
Creauno
unostack
stackopStack;
opStack;
while
(c’è
un
while (c’è unaltro
altrocarattere
carattereccda
dascandire){
scandire){
ififc cèèun
operando
then
aggiungi
un operando then aggiungiccalla
alla fine
fine della
della stringa
stringa Postfix;
Postfix;
else
if
c==
‘(‘
then
opStack.push(c);
else if c== ‘(‘ then opStack.push(c);
else
elseififcc==
==‘)’‘)’then
then{ {
while
(
opStack
while ( opStacknon
nonèèvuoto
vuotoAND
AND opStack.top()
opStack.top() !=
!= ‘(‘
‘(‘ ))
{ {aggiungi
aggiungiopStack.top()
opStack.top()alla
allafine
finedella
della stringa
stringa Postifix
Postifix ;; opStack.pop();
opStack.pop(); }}
opStack.pop();
//faccio
il
pop
di
‘(‘
opStack.pop(); //faccio il pop di ‘(‘
} }//fine
//finecaso
casocc==
==‘)’‘)’
Continua #
Strutture
StruttureDati
Dati 2011-2012
2011-2012
A.A.De
DeBonis
Bonis
Soluzione esercizio
esercizio 2: lo
Soluzione
Soluzione esercizio 2
pseudocodice
pseudocodice
else{ {////ccèèuno
unodegli
degli operatori
operatori +,
+, -,-, /,/, **
else
/*estraiamodallo
dallostack
stackeeaggiungiamo
aggiungiamo alla
alla stringa
stringa
/*estraiamo
tutti
gli
operatori
con
precedenza
maggiore
uguale di
di c*/
c*/
tutti gli operatori con precedenza maggiore oo uguale
while(opStack
(opStacknon
nonèèvuoto
vuotoAND
AND opStack.top()
opStack.top() !=
!= ‘(‘
‘(‘ AND
AND
while
prec(opStack.top())
>=
prec(c)
)
{
prec(opStack.top()) >= prec(c) ) {
aggiungi opStack.top() alla fine di Postfix; opStack.pop();
aggiungi opStack.top() alla fine di Postfix; opStack.pop();
}
}
opStack.push(c );
opStack.push(c );
} // fine else
} // fine else
} //fine del while esterno che serve a scandire la stringa input
} //fine del while esterno che serve a scandire la stringa input
while (opStack non è vuoto) //al termine svuoto lo stack
while (opStack non è vuoto) //al termine svuoto lo stack
{aggiungi opStack.top() alla fine di Postfix ; opStack.pop();
{aggiungi opStack.top() alla fine di Postfix ; opStack.pop();
}
}
Strutture Dati 2011-2012
A. De Bonis
Strutture Dati 2011-2012
A. De Bonis
666