Strutture Dati Astratte
Algoritmi e Strutture Dati
Molti algoritmi fanno uso strutture dati:
I
per sfruttare i servizi che queste mettono a disposizione;
I
per riversare su di esse la complessità di alcune operazioni
(senza doversi interessare della loro implementazione);
I
per gestire dati secondo determinate politiche.
Inoltre, le stesse strutture dati possono essere utilizzate da più
algoritmi:
Esempio: La struttura coda può essere utilizzata per:
I
gestire le richieste ad una stampante (coda di stampa);
I
regolare l’esecuzione di più processi (coda di priorità);
I
memorizzare la frontiera in una visita in ampiezza di un grafo;
Strutture Dati e Astrazione
Astrazione dei dati: Separazione del concetto “dato” dalla sua
rappresentazione.
“Un’astrazione deve denotare le caratteristiche essenziali di un
oggetto contraddistinguendolo da tutti gli altri oggetti e fornendo,
in tal modo, dei confini concettuali ben precisi relativamente alla
prospettiva dell’osservatore” (Grady Booch).
Strutture Dati Astratte (ADT): strutture dati definite a
prescindere dalla loro implementazione.
Opacità dei dati: ogni programma può accedere alla struttura
esclusivamente tramite i servizi (concetto di interfaccia).
L’ADT pila di interi
Esempio: Vogliamo definire una pila di interi:
typedef struct STACK { ...
}* Stack;
Quali servizi vogliamo dal tipo Stack?
I
Stack init( void ); inizializza una nuova pila;
I
void push( Stack, int ); inserisce un intero nella pila;
I
int pop( Stack ); toglie l’ultimo intero inserito e lo
resituisce;
I
int isEmpty( STACK * ); dice se la pila è vuota;
Tali servizi identificano l’interfaccia della struttura.
Vediamo una possibile soluzione: quella in C.
Strutture Dati Astratte
...in C
L’interfaccia è un file stack.h. Serve definire un tipo Stack.
/* stack.h */
typedef struct STACK {
int *store;
int top;
}* Stack;
Stack init( void );
void push( Stack, int );
int pop( Stack );
int isEmpty( Stack );
Non è un ADT!! Non si implementano le funzioni, ok, ma si
suppone che STACK sia implementato come un vettore!
Come risolvo il problema della rappresentazione del tipo STACK?
Dichiaro un tipo “puntatore all’etichetta struct STACK”.
/* stack.h */
typedef struct STACK* Stack;
Stack init( void );
void push( Stack, int );
int pop( Stack );
int isEmpty( Stack );
Posso definire la struttura STACK nel file di implementazione!
Ora siamo di fronte ad un ADT.
L’ADT Stack può essere implementato tramite vettore nel file di
implementazione:
/* stack.c */
#include <stdio.h>
#include <stdlib.h>
#include ‘‘stack.h’’
#define MAX DIM 100
struct STACK { int store[MAX DIM]; int top; };
Stack init( void ) { ... }
void push( Stack s, int i ) {...}
int pop( Stack s ) { ... }
int isEmpty( Stack s ) { ... }
Posso definire la struttura STACK nel file di implementazione!
Ora siamo di fronte ad un ADT.
Esempio di ADT per sorting
Nell’esempio visto a laboratorio, vediamo una ADT, Item, per
memorizzare oggetti generici su cui fare sorting.
Servizi di Item:
I
crea un nuovo Item (in modo casuale, per i test);
I
dati due Item, dimmi l’ordine (ordinamento totale);
I
dato un Item, scrivilo sullo schermo;
In questo modo, possiamo riscrivere tutti gli algoritmi che ordinano
vettori (di Item) astraendo da quali oggetti questi Item
rappresentano e da quale ordinamento sia definito su questi oggetti.