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.