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