Pile e code
ADT e strutture dati per la
rappresentazione di sequenze ad
accesso LIFO e FIFO
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le Pile
Una pila è una struttura dati lineare, alla quale
gli elementi possono essere aggiunti o sottratti
da un solo estremo:
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le Pile
LIFO:
LIFO: Last
Last In,
In, First
First Out
Out
Push
a
b
c
d
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le Pile
LIFO:
LIFO: Last
Last In,
In, First
First Out
Out
a
b
c
d
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le Pile
LIFO:
LIFO: Last
Last In,
In, First
First Out
Out
Pop
a
b
c
d
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
ADT delle pile
Sintassi
Tipi: TipoEl, Stack
Operatori:
NewStack: void → Stack
Push: TipoEl, Stack → Stack
Top: Stack → TipoEl
Pop: Stack → Stack
IsEmpty?: Stack → Boolean
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
ADT delle Pile
Semantica
NewStack():
Post: produce una pila vuota
IsEmtpty?(s):
Post: true se s = ∅, false altrimenti
Push(e, s):
Post: ritorna la pila ottenuta aggiungendo
e ad s come el. emergente
Top(s):
Pre: s ≠ ∅; Post: ritorna l’emergente
Pop(s):
Pre: s ≠ ∅; Post: ritorna s meno
l’emergente
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di pile con vettori
1
S.top
S.n
S.vett
Push(e, S)
if S.top < S.n then
S.top ← S.top + 1
O(1)
S.vett[S.top] ← e
else ERROR
// non abbiamo un pred. “pila piena” nella specifica
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di pile con vettori
1
S.top
S.n
S.vett
Pop(S)
O(1)
S.top ← S.top − 1
// non trattiamo l’errore “pila vuota” perché la
// precondizione di Pop è che la pila non sia tale
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di pile con vettori
1
S.top
S.n
S.vett
Top(S)
return S.vett[S.top]
// non trattiamo l’errore “pila vuota” perché la
// precondizione di Pop è che la pila non sia tale
O(1)
IsEmpty?(S)
return S.top < 1
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di pile come liste
S.head
…
∅
Push(e, S)
Top(S)
S.head ← Cons(e, S.head)
return S.head.info
Pop(S)
IsEmpty?(S)
S.head ← S.head.next
return S.head = nil
Tutte operazioni O(1)
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Inversione di una lista
Reverse_iter (L) // prima versione
// Post: ritorna la lista degli el. di L in ordine inverso
S ← NewStack()
L′ ← NewList()
while L ≠ nil do // inserisce sulla pila tutti gli el. di L
Push(Head(L), S)
L ← Tail(L)
while not IsEmpty?(S) do
// estrae da S tutti gli el. e li inserisce in fondo ad L′
Append(L′, Top(S))
L′ è una copia della pila,
Pop(S)
dunque per il principio LIFO, è
return L′
l’inversa di L
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Inversione di una lista
Reverse_iter (L)
// Post: ritorna la lista degli el. di L in ordine inverso
L′ ← NewList()
while L ≠ nil do // inserisce sulla pila tutti gli el. di L
L′ ← Cons(Head(L), L′)
L ← Tail(L)
Se si fanno solo inserimenti in
return L′
testa, una lista è una pila:
possiamo allora usare
direttamente L′
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Inversione di una lista
Reverse_rec (L)
// Post: ritorna la lista degli el. di L in ordine inverso
return Reverse_aux (L, nil)
L’algoritmo è il
Reverse_aux (L, L′ )
medesimo (ric. di
coda): usa L′ come
fosse una pila
// Post: rit. l’inversa di L davanti ad L′
//
L′ L) ′=) =L′r(L, [a | L′ ])
// r([
r([a],| L],
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le code
FIFO:
FIFO: First
First In,
In, First
First Out
Out
Enqueue
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Le code
FIFO:
FIFO: First
First In,
In, First
First Out
Out
Dequeue
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
ADT delle code
Sintassi
Tipi: TipoEl, Queue
Operatori:
NewQueue: void → Queue
Enqueue: TipoEl, Queue→ Queue
Dequeue: Queue→ TipoEl
IsEmpty?: Queue → Boolean
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
ADT delle Code
Semantica
NewQueue():
Post: produce una coda vuota
IsEmtpty?(q):
Post: true se q = ∅, false altrimenti
Enqueue(e, q):
Post: ritorna la coda ottenuta
aggiungendo e come ultimo el. in q
Dequeue(q):
Pre: q ≠ ∅;
Post: ritorna il primo elemento di q
togliendolo da q
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di code con vettori
Q.front
Q.rear
Q.n - 1
Q.vett
Q.rear
ma anche
Q.front
Q.n - 1
Q.vett
Per sfruttare lo spazio
liberato da Dequeue si
gestisce il vettore come
fosse circolare
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di code con vettori
Q.front
Q.rear
Q.n - 1
Q.vett
Q.front
Q.rear
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Quando la coda è piena
Q.front
Q.rear = Q.n -1
Q.vett
oppure
Q.rear Q.front
Q.n - 1
Q.vett
Enqueue (e, Q)
if not S.empty and (Q.rear + 1) mod Q.n = Q.front
then ERROR // il succ. di rear è frint: coda piena
else Q.rear ← (Q.rear + 1) mod Q.n
Il successivo si
Q.vett[Q.rear] ← e
calcola modulo n
Q.empty ← false
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Quando la coda è vuota
Q.front = Q.rear
Q.n - 1
Q.vett
Q.rear Q.front
Q.n - 1
Q.vett
Dequeue (Q)
succ(rear) = front non
e ← Q.vett[Q.front]
basta per distinguere
Q.front ← (Q.front + 1) mod Q.n
coda piena/coda vuota
if Q.front = (Q.rear + 1) mod Q.n
// il succ. di rear è front: coda vuota
then Q.empty ← true
return e
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di code con liste
Q.front
…
∅
Q.rear
Enqueue (e, Q)
if Q.rear = nil then // la coda è vuota
Q.rear ← Cons(e, nil), Q.front ← Q.rear
else
Q.rear.next ← Cons(e, nil), Q.rear ← Q.rear.next
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6
Realizzazione di code con liste
Q.front
…
∅
Q.rear
Dequeue (Q)
IsEmpty? (Q)
e ← Q.front.info
return Q.front = nil
Q.front ← Q.front.next
if Q.front = nil then Q.rear ← nil
return e
Anche qui tutte
operazioni O(1)
Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 6