Le strutture informative Corso di Informatica 2 a.a. 2003/04 Lezione 5 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Che cos’è una struttura dati? modo sistematico di rappresentare ed Struttura dati = organizzare dati 0010011010010111 numero intero rappr. in binario a f k z q d i w vettore Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Come rappresentare collezioni? Una soluzione è il vettore: dim 1 0 v proxlibero v dim proxlibero array Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Come rappresentare collezioni? Una soluzione è il vettore: typedef struct vettrec { int dim, proxlibero; T *array; v } VettRec; typedef VettRec* Vettore; dim proxlibero array Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 I record Un record è una tupla di valori di tipi possibilmente diversi acceduti attraverso etichette: struct <nome struttura> { <tipo1> <etichetta campo1>; ... <tipok> <etichetta campok>; } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 I record struct puntocolorato { int x, y; // coord. sullo schermo Colore c; // tipo enumerato } ... struct puntocolorato p; p.x = 44; p.y = 12; p.c = rosso; selettore del campo Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Allocazione di un Vettore Vettore NuovoVettore (int dim) { Vettore v = new VettRec; v->dim = dim; v->proxlibero = 0; v->array = new T[dim]; return v; Tutte queste istruzioni debbono essere ripetute per ciascun nuovo vettore } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Uso di un Vettore Vettore A = NuovoVettore(10) // A potrà contenere al più 10 el. // supponendo che T == int, aggiungiamo // un intero alla collezione A if (A->proxlibero < A->dim) A->array[v->proxlibero++] = 7; A->array[i] abbrevia(*A).array[i] ecc. Per accedere ad A bisogna ricordare molte cose Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Uso di un Vettore void Aggiungi (Vettore v, T valore) // Pre: in v c’è posto per un nuovo // valore // Post: aggiunge valore a quelli in v { } v->array[v->proxlibero++] = valore; bool VettorePieno (Vettore v) // Post: ritorna true sse v è pieno { return v->proxlibero == v->dim; } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Uso di un Vettore Vettore A = NuovoVettore(10) // A potrà contenere al più 10 el. // supponendo che T == int, aggiungiamo // un intero alla collezione A if (!VettorePieno(A)) Aggiungi(A,7); Codice che non richiede la conoscenza della realizzazione Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Deallocazione • La memoria dinamica allocata può essere recuperata usando la funzione delete: delete <puntatore> • Per deallocare un vettore non occorre ricordarne la dimensione: delete [] <nome vettore> • Per deallocare una struttura complessa occorrono tante chiamate di delete quante sono state quelle di new Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Deallocazione di un Vettore void DeallocaVettore (Vettore v) { delete [] v->array; // dealloca il vettore dei valori delete v; // dealloca il record di accesso } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Un esempio più complesso: matrici typedef MatrRec* Matrice; typedef struct matrmec { int righe, colonne; T **vecrighe; } MatrRec; n m m n Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Un esempio più complesso: matrici Matrice NuovaMatrice (int r, int c) { Matrice m; m = new MatrRec; m->righe = r; m->colonne = c; m->vecrighe = new int*[r]; for (int i = 0; i < r; i++) m->vecrighe[i] = new T[c]; return m; } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Deallocazione di Matrice void DeallocaMatrice (Matrice m) { for(int i = 0; i < m->righe; i++) delete [] m->vecrighe[i]; delete [] m->vecrighe; delete m; } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Le liste Come struttura dati una lista è una sequenza di record, ciscuno dei quali contiene un campo che punta al successivo: info next l 2 5 9 1 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Le liste typedef struct nodo* Lista; typedf struct nodo { T info; Lista è ricorsivo Lista next; } Nodo; l 2 5 9 1 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 La funzione Cons Lista Cons (T x, Lista l) { Lista nl = new Nodo; nl->info = x; nl->next = l; return nl; Cons è un allocatore } Cons(4, l ) 4 l 2 5 9 1 Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Le funzioni Head e Tail T Head (Lista l) // Pre: l non è vuota Può essere un L-value { return l->info; } Lista& Tail (Lista l) // Pre: l non è vuota { return l->next; l Tail(l ) Head(l ) = 2 2 5 } … Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 La lista vuota bool ListaVuota (Lista l) { … return l == NULL; 5 } Al fondo di ogni lista c’è la lista vuota, ossia un puntatore a NULL void StampaLista (Lista l) { while (!ListaVuota(l)) { cout << Head(l) << " "; l = Tail(l); } } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista Cons(x,p->next); x p Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista p->next = Cons(x,p->next); x p L’inserimento è O(1) posto che si conosca p Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento iterativo void Inserimento (T x, int i, Lista& l) // Pre: 1 <= i <= lunghezza(l) + 1 // Post: inserisce x in l come i-esimo el. { effetto collaterale if (i == 1) l = Cons(x, l); else // 1 < i <= lunghezza(l) + 1 { int j = 1; Lista p = l; while (j < i-1 && p != NULL) Se p è da cercare allora l’inserimento è O(n) // inv. p punta al j-esimo el. di l { j++; p = Tail(p);} if (p != NULL) // allora j == i-1, Tail(p) = Cons(x, Tail(p)); } } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Un metodo ricorsivo Lista InsRic (T x, int i, Lista l) // Pre: 1 <= i <= lunghezza(l) + 1 // Post: inserisce x in l come i-esimo el. { if (i == 1) return Cons(x, l); else { Tail(l) = InsRic (x, i-1, Tail(l)); return l; } } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Cancellazione da una lista temp = p->next; p->next = p->next->next p Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Cancellazione da una lista delete temp; p temp Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Liste bidirezionali Realizzazione di liste bidirezionali con sentinella (liste doppie) sentinella info 1 12 pred 7 3 next L Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Liste bidirezionali Realizzazione di liste bidirezionali circolari con sentinella (liste doppie circolari) 1 12 7 3 L Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista 1 12 p 7 q Se la posizione è implementata con un puntatore allora Insert(a, L, p) è O(1) temp = p->next P->next = q, q->pred = p Temp->pred = q, q->next = temp Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista 1 12 p 7 Se invece p = posi è un indice allora Insert(a, L, p) è O(n) !! q temp = p->next P->next = q, q->pred = p Temp->pred = q, q->next = temp Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista sentinella 12 p 7 L’inserimento avviene in modo uniforme al principio … q temp = p->next P->next = q, q->pred = p Temp->pred = q, q->next = temp Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Inserimento in una lista … 12 p temp punta alla sentinella 7 q … come alla fine della lista temp = p->next P->next = q, q->pred = p Temp->pred = q, q->next = temp Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Cancellazione da una lista 1 12 7 p p->next = p->next->next p->next->pred = p • Delete(L, p) è O(1) se p è un puntatore, O(n) se è un indice • la cancellazione è uniforme all’inizio ed alla fine della lista Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 La lista vuota Nel caso della lista doppia con sentinella, il valore nil non è un puntatore NULL: L bool IsEmpty? (Lista l) { return l->next == l; // L punta alla sentinella } Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5