Sei sulla pagina 1di 23

Cos’è una struttura astratta

di dati?
Struttura Insiemi finiti di dati
astratta di tra i quali esistono
dati delle relazioni logiche.

Ha la funzione di un contenitore
che può essere riempito con dati di
volta in volta di tipo diverso.

Esempi di insiemi di dati correlati tra


loro da relazioni logiche

? Elenco telefonico

? Schedario di una biblioteca

? Elenco degli alunni di una classe

? Le tessere degli abbonati


di un garage di autovetture

1
Operazioni relative alle strutture dati

Accesso a un elemento (o nodo) per leggere il


contenuto.
Ricerca di un elemento con un determinato
contenuto.
Inserimento di un nuovo elemento.

Modifica del contenuto di un elemento tramite


la ricerca e l’accesso al nodo.

Cancellazione di un elemento senza alterare le


connessioni con gli altri nodi.

Struttura astratta di dati


? Il processo di
realizzazione delle
strutture della
memoria del
calcolatore
prende il nome di
implementazione.

2
Struttura astratta di dati

Quando la dimensione è definita


nel momento di creazione della
Statica struttura e non può essere
modificata.

Quando non è posto alcun vincolo


Dinamica sulla dimensione della struttura.

Struttura astratta di dati

Quando un nodo può avere al più un


Lineare nodo che lo precede e al più un
nodo che lo segue.

Non Quando un nodo può avere due o


più nodi che lo precedono o lo
lineare seguono.

3
Strutture informative
significative
? Array
? Tabelle
? Lista lineare
? Lista concatenata
? Pila
? Coda
? Grafi
? Alberi

La Pila
Una pila (detta anche STACK) è una struttura
dati lineare, i cui elementi possono essere inseriti
o estratti da un’unica estremità (LIFO).

LIFO è acronimo di Last In First Out, ovvero l’ultimo ad


entrare è il primo ad uscire.

4
5
6
7
Modalità d’impiego delle pile
? La pila è un tipo di dato astratto che trova impiego
nell’organizzazione dei dati in memoria centrale in
molti sistemi operativi, nonché nella memorizzazione
degli indirizzi di ritorno delle funzioni.
? Tale struttura è comune nei processi nei quali un
problema in corso d’esame viene lasciato
temporaneamente sospeso per affrontare un
sottoproblema che, a sua volta è lasciato in sospeso,
per affrontare un nuovo sottoproblema e così via
finché l’ultimo sottoproblema generato è messo in
testa alla pila dei vari sottoprogrammi da risolvere.

8
Operazioni sulle Pile
Le operazioni che si possono definire per una
pila (stack) sono:
? Push: aggiunge nuovo elemento alla pila.
? Pop: elimina l’elemento emergente dalla pila
restituisce l’elemento inserito da meno tempo!
? TopElem: restituisce il valore del primo elemento
della pila, senza estrarlo.
? IsEmpty: per verificare se la pila è vuota
(restituisce true se la pila non ha elementi).
? IsFull: per verificare se la pila è piena.
? Clear: per cancellare tutti i dati.

La pila come struttura statica


? In alcuni casi le strutture LIFO hanno una
dimensione limitata, per cui è necessario
definire un valore massimo di elementi
inseribili.
? Per l’implementazione di una pila servono:
? uno spazio di memoria ordinato, dove inserire gli
elementi;
? un indice per sapere quale è l’ultimo elemento
inserito.

9
La pila come struttura statica
? L’indice deve tener conto di quanti elementi
ci sono nella pila.
? Si utilizza un array per memorizzare gli
elementi e un numero intero che indica la
prima posizione libera dello stack.

Top = 0 Pila vuota 5


4
Top=max Pila piena 3
top 5 2
1

Operazioni sulle pile


? Una pila (stack) si definisce astrattamente come una
struttura dati su cui siano definite alemeno quattro
operazioni:
1. Push(e,s) : aggiunge e alla pila s
2. Pop(s) : elimina l’elemento emergente da s
3. Top(s) : ritorna il valore dell’emergente di s
4. IsEmpty(s): ritorna true se s non ha elementi.

Nota: se s è vuota, Pop(s) e Top(s) sono indefinite.

10
11
Pile realizzate con vettori (1)
typedef struct stackframe {
s
int dim; // dimensioni pila
int top_el; // indice emergente
T* vel; // vettore elementi
dim } StackFrame;
top_el typedef StackFrame* Stack;

12
Pile realizzate con vettori (2)
Stack NewStack(int n)
// alloca una pila di max n elementi
{ Stack s = (Stack) malloc (sizeof(StackFrame));
s->dim = n; s->top_el = -1;
s->vel = (T*) malloc (sizeof(T)*n);
return s;
}
void DeleteStack(Stack s) // deallocatore
{ free(s->vel); free(s);
}

Pile realizzate con vettori (3)


typedef enum {false, true} boolean;
boolean Push(T el, Stack s)
// true se in s vi e’ posto per un nuovo elemento
// e lo aggiunge ad s come emergente
// false altrimenti
{ if (s->top_el < s->dim-1) // c’e’ posto in s
{s->vel[++top_el] = el; return true;}
else return false;
}

13
Pile realizzate con vettori (4)
void Pop(Stack s)
// pre: s non e’ vuoto
// post: rimuove l’elemento emergente da s
{ s->top_el--;}
T Top(Stack s)
// pre: s non e’ vuoto
// post: ritorna il valore dell’el. emergente in s
{ return s->vel[top_el];}
boolean IsEmpty(Stack s) // true se s e’ vuota
{ return s->top_el == -1;}

Notazione polacca postfissa


? Nella notazione polacca postfissa per le
espressioni aritmetiche un operatore
segue i suoi operandi. É definita dalla
grammatica:
<espressione> ::= <numerale> |
<espressione> <espressione>
<operatore>

Esempio: l’espressione in notazione infissa:


(7 + 3) £ 5
si traduce in:
7 3+5£

14
Algoritmo di valutazione
Valuta (Stringa espr)
// espr è fatta di parole separate da spazi
s := pila vuota
while (scansione di espr non è finita)
e := prossima parola di espr;
if (e è un numerale) then Push(e,s)
else // e è un operatore
n := Top(s); Pop(s); // l’ordine di lettura ed eliminaz.
m := Top(s); Pop(s); // dalla coda è importante …
op := ????? oppure ? a seconda di e;
Push(m op n, s) // … qui
return Top(s). // se espr è un’espr. in not. polacca, s ha un solo el.

Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 4

15
Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 8
4

Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 7
8
4

16
Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 3
7
8
4

Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 10
8
4

17
Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 80
4

Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 2
80
4

18
Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 40
4

Esecuzione dell’algoritmo
4 8 7 3 + ? ? ? ?

top 44

19
Gestione statica e gestione dinamica
Le aree di memoria richieste dal
codice sorgente vengono
Gestione predisposte dal compilatore
statica attraverso la dichiarazione delle
variabili e allocate all’avviamento
del programma eseguibile.

Le istruzioni per l’allocazione di


Gestione nuova memoria vengono
dinamica richiamate durante l’esecuzione
del programma.

La pila come struttura dinamica


Push Pop
dati dati dati
3
link

dati
Si distingue una 2
parte di dati e una
link
parte di puntatori
di collegamento dati
1
(link). link

20
typedef struct PilaElem *TipoPila;
struct PilaElem {
TipoElemPila val;
TipoPila next;
};

void InitPila(TipoPila *p)


{
*p = NULL;
} /* InitPila */

bool TestPilaVuota(TipoPila p)
{
return (p == NULL);
} /* TestPilaVuota */

21
void TopPila(TipoPila p, TipoElemPila *v)
{
if (TestPilaVuota(p))
printf("ERRORE: PILA VUOTA\n");
else
*v = p->val;
} /* TopPila */

void Push(TipoPila *p, TipoElemPila v)


{
TipoPila paux;

paux = malloc(sizeof(struct PilaElem));


paux->val = v;
paux->next = *p;
*p = paux;
} /* Push */

22
void Pop(TipoPila *p, TipoElemPila *v)
{
TipoPila paux;
if (TestPilaVuota(*p))
printf("ERRORE: PILA VUOTA\n");
else {
*v = (*p)->val;
paux = *p;
*p = (*p)->next;
free(paux);
}
} /* Pop */

23

Potrebbero piacerti anche