Realizzazione software
• Due fasi:
1. Specifica dell'algoritmo
1.a
1.b
Definizione dei dati
Definizione della modalità della loro
elaborazione
2. Realizzazione algoritmo con un particolare
linguaggio (traduzione)
Tipi di dati
• Tipo di dato astratto: oggetto matematico definito da tre
componenti:
– insieme di valori che definisce il dominio
– insieme di operazioni sul dominio
– insieme di costanti
• Esempio: tipo booleano:
• {true, false}
• and, or, not, ...
• true, false
Tipi di dati
• Tipo di dato concreto: si riferisce all'uso del dato in un
particolare linguaggio
• Per definire un tipo di dato concreto occorre:
– definire le proprietà astratte
– definire i vincoli imposti dal linguaggio scelto
• ad esempio: come dichiararlo, utilizzarlo, accedere alle sue parti,...
Rappresentazione di
un nuovo tipo di dato
• Per rappresentare un nuovo tipo di dato, può essere necessario
utilizzare tipi di dati già esistenti
• Esempio: tipo di dato: "insieme [1..5]"
• Realizzato con un vettore di 5 elementi
• I metodi sono composizioni dei metodi utilizzati dai dati
componenti
Rappresentazione di
un nuovo tipo di dato
• Esempio:
– inserimento di un elemento nell'insieme
– rimozione di un elemento dall'insieme
– svuotamento dell'insieme
– controllo della presenza di un elemento
– controllo dello stato dell'insieme (pieno, vuoto, stati intermedi)
Rappresentazione dei dati
• La rappresentazione di un nuovo dato non è univoca
• I criteri di scelta sono:
– la correttezza e
– l'efficienza della rappresentazione, misurata da:
• occupazione in memoria
• costo di esecuzione delle operazioni
Diverse rappresentazioni
• Esempio: insieme di interi [1..5]
– con un vettore di 5 elementi booleani
– con un unico intero di 5 bit
• Differenza di efficienza:
– Inserimento di un el.:

– Controllo dello stato di un el.:  
– Azzeramento:

– Unione:

Vettori e matrici
• Si mettono in corrispondenza un insieme di indici e gli elementi
del vettore
– Gli indici sono definiti interi
– I metodi sono generalmente:
memorizza e accedi
• Una matrice è definita come un vettore a due dimensioni
Rappresentazione di vettori
• In locazioni di memoria contigue
• Si definisce l'indirizzo della prima locazione e la dimensione di
ogni elemento
• Accesso all'elemento i-esimo:
ind(el i) = ind(el 0) + i*size(el)
Vettori a più dimensioni
• Esempio a due dimensioni:
– Row major order
• Accesso all'elemento (i,j)-esimo:
ind( el i,j ) = ind(el 0,0) + (j+i*N)*size(el)
• Facile estensione a più di due dimensioni
Rappresentazione
compatta di vettori
• Matrici sparse con valore predominante
– per velocizzare l'elaborazione
– per risparmiare memoria
• Esempio con vettore a tre componenti
– memorizzazione dimensione matrice e valore predominante
Rappresentazione
compatta di vettori
• Metodi di accesso agli elementi:
– accedi (complesso)
– memorizza (molto complesso, richiede shift)
• Funzioni composte:
– controllo dello stato
– controllo del numero degli elementi
• Risparmio di memoria
Le liste semplici
• I valori di una lista sono sequenze di valori elementari, detti
atomi
• Esempio di lista di interi mediante rappresentazione parentetica:
( 8 25 6 87 54 )
• Caratteristiche:
– lunghezza non definita a priori
– presenza della lista nulla ( )
Metodi sulle liste
•
•
•
•
•
Lunghezza (numero di elementi)
cons(el, lista) per inserire un elemento in testa alla lista
car(lista) determina il primo elemento
cdr(lista) fornisce una copia della lista senza il primo elemento
null(lista) verifica se la lista è vuota
Rappr. delle liste semplici
• Pochi linguaggi dispongono del tipo concreto lista
• Vi sono due tipi di rappresentazione:
– rappr. sequenziale
– rappr. collegata
Rappresentazione sequenziale
• E' rappresentata da:
– un vettore monodimensionale i cui elementi contengono un atomo
– un intero (primo) che denota l'indice del vettore che identifica il primo
elemento
– un intero (lunghezza) che denota il numero di elementi nella lista
Rappresentazione sequenziale
(5 1 21 45 78)
5
1
21
45
78
12
1
7
1
2
3
4
5
6
7
8
primo = 1
lunghezza = 5
Rappresentazione sequenziale
• Implementazione dei metodi
• Svantaggi:
– occupazione fissa di memoria
– limiti nell'estensione della lista
– inefficienza di alcuni metodi
Rappresentazione collegata
• Ad ogni elemento è associato un riferimento che serve a
determinare il successore
• La sequenza non è più rappresentata dall'adiacenza fisica in
memoria, ma da una informazione logica
Rappresentazione collegata
• Implementazione dei metodi:
– eliminazione primo elemento
– aggiunta di un elemento in testa
– eliminazione di un elemento generico
– aggiunta di un elemento in una posizione generica
Rappresentazione collegata
• Vantaggio:
– non più necessario spostare elementi (solo modifiche ai riferimenti)
• Svantaggio:
– per accedere ad un elemento è necessario scandire tutta la lista (cioè
non è noto l'indirizzo del generico elemento)
Implementazione della rappresentazione
collegata
• Vi sono due modi per implementare la rappresentazione
collegata:
– utilizzando gli array
– utilizzando i puntatori
Rappresentazione collegata mediante array
• Si associa ad ogni elemento della lista una componente
dell'array costituita da:
– il valore dell'elemento della lista
– il riferimento all'elemento successivo (indice dell'array)
Rappresentazione collegata mediante array
(5 1 21 45 78)
21
4
5
6
?
?
45
7
?
?
1
1
78
0
?
?
1
2
3
4
5
6
7
8
inizio = 2
Rappresentazione collegata mediante array
• Metodi:
– l'azzeramento e l'eliminazione di elementi sono operazioni semplici
– l'inserimento di elementi necessita della determinazione di una
posizione vuota che si può realizzare in due modi:
• scansione dell'intera lista
• utilizzo della lista libera (esempi)
Rappresentazione collegata mediante array
• Vantaggi:
– non vengono spostati elementi
– linguaggi in cui l'unico dato struttturato è l'array
• Svantaggi:
– gestione della lista libera
– rimane il problema della dimensione massima fissata dalla dimensione
dell'array
– richiede più memoria a causa dei riferimenti
Rappresentazione collegata mediante puntatore
• Il tipo puntatore è un tipo di dato i cui valori rappresentano
indirizzi in memoria
• Le operazioni usualmente disponibili sono:
– accesso alla locazione puntata
– richiesta di una nuova locazione libera
– rilascio della locazione non più utilizzata
Rappresentazione collegata mediante puntatore
• Ogni elemento della lista è composto da:
– il valore dell'elemento della lista
– un puntatore che identifica la locazione di memoria in cui è
memorizzato l'elemento successivo
• L'elemento iniziale è un puntatore
Rappresentazione collegata mediante puntatore
• Vantaggi:
– stessi vantaggi della rappresentazione collegata mediante array e in
più non c'è limite alla lunghezza massima
• Svantaggi:
– la ricerca richiede la scansione completa
L'utilizzo dei puntatori è critico
• L'utilizzo dei puntatori permette di referenziare zone di
memoria; è critico perché:
– permette di modificare aree di memoria che possono contenere
informazioni vitali
– se mal utilizzato, può portare all'esaurimento della memoria disponibile
(garbage collection)
Rappresentazione collegata
• Per migliorare l'efficienza di alcune operazioni sono state
concepite due varianti:
– Rappresentazione collegata circolare
– Rappresentazione collegata simmetrica
Rappresentazione
collegata circolare
• L'ultimo elemento non contiene un riferimento nullo, ma il
riferimento al primo elemento della lista
• Vantaggi:
– utilizzo come buffer circolare
Rappresentazione
collegata simmetrica
• Ogni elemento contiene anche il riferimento all'elemento
precedente
• Vantaggi:
– la lista si può scandire in entrambe le direzioni
– si semplifica l'inserimento in posizione precedente ad un dato
elemento
Liste composite
• Estensione del concetto di lista
• Gli elementi della lista possono a loro volta essere delle liste
• Rappresentazione parentetica:
( 5 () 6 ( 7 8 ) ( 9 (12) 3 ) 14 )
• Nell'esempio, l'atomo può essere una lista o un numero
Rappresentazione
del singolo nodo
• Esistono due varianti:
– l'atomo contiene sia un puntatore ad una lista che lo spazio per
memorizzare un numero; un ulteriore booleano li seleziona
– l'atomo contiene lo spazio per memorizzare solo il più esteso tra il
puntatore alla lista e il numero; un ulteriore booleano li seleziona
Rappresentazione
del singolo nodo
• Le due varianti si riferiscono a:
strutture (struct)
typedef struct {
int giorno;
int mese;
int anno;
} data;
unioni (union)
typedef union {
int numero;
char nome[10];
} cliente;
Recupero della memoria
• Garbage collection
(recupero memoria non più utilizzata)
• Può avvenire:
– manualmente a carico del programmatore
– automaticamente a carico del traduttore del linguaggio (serve marcare
le aree allocate e gestire la lista libera)
Le pile
• La pila è un tipo di dato con struttura LIFO
• Definizione:
– {pila, elemento, boolean}
– {top, push, pop, test_pila_vuota}
• top:
pila  elemento
• push: pila x elemento  pila
• pop:
pila  pila
• test_pila_vuota: pila  boolean
(cons)
(cdr)
(car)
(null)
– {pila_vuota}
Le pile
• A differenza delle liste gli inserimenti e le cancellazioni posso
essere effettuati solo sulla cima della pila (non avvengono
spostamenti degli elementi)
• Tipo di dato fondamentale
Le code
• La coda è un tipo di dato con struttura FIFO
• Definizione:
– {coda, elemento, boolean}
– {primo, in_coda, out_coda, test_coda_vuota}
• primo:
coda  elemento
• in_coda: coda x elemento  coda
• out_coda: coda  coda
• test_coda_vuota: coda  boolean
(cons)
(cdr)
(car)
(null)
– {coda_vuota}
Requisiti delle pile e delle code
• Requisiti delle pile:
– un puntatore che determini la cima
– le operazioni di accesso sono semplici
• Requisiti delle code:
– due puntatori che puntino alla cima e alla coda
– le operazioni di accesso sono poco più complesse