Gest ione di list e in C Politecnico di Milano Sede di Cremona Gianpaolo Cugola Dipartimento di Elettronica e Informazione cugola@elet.polimi.it http://www.elet.polimi.it/~cugola Strutture dinamiche Gli array ci permettono di memorizzare un insieme di dati dello stesso tipo Deve essere noto staticamente il numero massimo di dati da memorizzare C è uno spreco di memoria ogni qual volta la quantità di dati effettivamente da memorizzare sia inferiore al numero massimo previsto È utile poter costruire strutture dati capaci di crescere al crescere delle necessità del programma e di liberare memoria quando non è più necessaria Informatica A - Cugola 2
Strutture dinamiche Il C offre due importanti funzioni (in stdlib.h) malloc Richiede come parametro la dimensione dell oggetto creato Restituisce un puntatore all oggetto free Richiede come parametro il puntatore a un oggetto creato da malloc Rende la memoria utilizzata dall oggetto disponibile per nuovi oggetti Si usa lo heap Informatica A - Cugola 3 Strutture dinamiche Vantaggi: Si creano solo i contenitori che servono per la particolare istanza del problema Aumenta la flessibilità d uso Svantaggi L uso è più complesso Si possono creare dangling pointers Informatica A - Cugola 4
Liste Sono le strutture dinamiche più semplici Una lista è composta da un insieme di nodi Ciascun nodo contiene: Un dato Il puntatore al nodo successivo Informatica A - Cugola 5 Nodi e liste Nodo info prox 5 8 2 4 Lista contenente 4 elementi Informatica A - Cugola 6
Le liste in C typedef struct Nodo { TipoElemento info; struct Nodo *prox; Nodo; typedef Nodo *Lista; Informatica A - Cugola 7 Inizializzazione Lista inizializza() { return NULL; Lista lista; lista = inizializza(); Informatica A - Cugola 8
Inizializzazione forma alternativa void inizializza(lista *l) { *l = NULL; Lista lista; inizializza(&lista); Informatica A - Cugola 9 Controllo lista vuota boolean listavuota(lista l) { return l == NULL; Lista lista; if(listavuota(lista)) Informatica A - Cugola 10
Inserimento in testa Lista inserisciintesta(lista l, TipoElemento el){ Nodo *temp; temp >info = el; temp >prox = l; return temp; i2 lista = inserisciintesta(lista, i1); lista = inserisciintesta(lista, i2); i1 Informatica A - Cugola 11 Inserimento in testa forma alternativa void inserisciintesta(lista *l, TipoElemento el){ Nodo *temp; temp >info = el; temp >prox = *l; *l=temp; inserisciintesta(&lista, i1); inserisciintesta(&lista, i2); i2 i1 Informatica A - Cugola 12
Inserimento in coda Lista inserisciincoda(lista l, TipoElemento el) { Nodo *temp; if (listavuota(l)) { temp->info = el; temp->prox = NULL; return temp; else { for(temp=l; temp->prox!=null; temp=temp->prox) ; temp->prox = malloc(sizeof(nodo)); temp->prox->info = el; temp->prox->prox = NULL; return l; lista = inserisciincoda(lista, i1); lista = inserisciincoda(lista, i2); i1 i2 Informatica A - Cugola 13 Inserimento in coda forma alternativa void inserisciincoda(lista *l, TipoElemento el) { Nodo *temp; if (listavuota(*l)) { temp->info = el; temp->prox = NULL; *l = temp; else { for(temp=*l; temp->prox!=null; temp=temp->prox) ; temp->prox = malloc(sizeof(nodo)); temp->prox->info = el; temp->prox->prox = NULL; i1 i2 inserisciincoda(&lista, i1); inserisciincoda(&lista, i2); Informatica A - Cugola 14
Inserimento in coda forma ricorsiva Lista inserisciincoda(lista l, TipoElemento el) { Nodo *temp; if (listavuota(l)) { temp >info = el; temp >prox = NULL; return temp; else { l->prox = inserisciincoda(l >prox, el); return l; lista = inserisciincoda(lista, i1); lista = inserisciincoda(lista, i2); i1 i2 Informatica A - Cugola 15 Inserimento in ordine Lista inserisciinordine(lista l, TipoElemento el) { Nodo *temp, *puntcorrente, *puntprecedente; puntprecedente = NULL; for(puntcorrente=l; puntcorrente!=null && el>puntcorrente->info; puntcorrente=puntcorrente->prox) { puntprecedente = puntcorrente; temp->info = el; temp->prox = puntcorrente; if (puntprecedente!= NULL ) { /* Inserimento interno alla lista */ puntprecedente->prox = temp; return l; else return temp; /* Inserimento in testa alla lista */ lista = inserisciinordine(lista, i2); lista = inserisciinordine(lista, i1); i1 i2 Informatica A - Cugola 16
Inserimento in ordine forma alternativa void inserisciinordine(lista *l, TipoElemento el) { Nodo *temp, *puntcorrente, *puntprecedente; puntprecedente = NULL; for(puntcorrente=*l; puntcorrente!=null && el>puntcorrente->info; puntcorrente=puntcorrente->prox) { puntprecedente = puntcorrente; temp->info = el; temp->prox = puntcorrente; if (puntprecedente!= NULL ) { /* Inserimento interno alla lista */ puntprecedente->prox = temp; else *l = temp; /* Inserimento in testa alla lista */ inserisciinordine(&lista, i2); inserisciinordine(&lista, i1); i1 i2 Informatica A - Cugola 17 Cancellazione di un elemento Lista cancella(lista l, TipoElemento el) { Nodo *temp, *puntcorrente, *puntprecedente; if(listavuota(l)) return l; if(l->info==el) { temp = l; l = l->prox; free(temp); else { puntprecedente=null; for(puntcorrente=l; puntcorrente!=null && puntcorrente->info!=el; puntcorrente=puntcorrente->prox) { puntprecedente = puntcorrente; if(puntcorrente!=null && puntcorrente->info==el) { temp=puntcorrente; puntprecedente->prox = puntcorrente->prox; free(temp); return l; Informatica A - Cugola 18
Cancellazione di un elemento forma alternativa void cancella(lista *l, TipoElemento el) { Nodo *temp, *puntcorrente, *puntprecedente; if(listavuota(*l)) return; if((*l)->info==el) { temp = *l; *l = (*l)->prox; free(temp); else { puntprecedente=null; for(puntcorrente=*l; puntcorrente!=null && puntcorrente->info!=el; puntcorrente=puntcorrente->prox) { puntprecedente = puntcorrente; if(puntcorrente!=null && puntcorrente->info==el) { temp=puntcorrente; puntprecedente->prox = puntcorrente->prox; free(temp); Informatica A - Cugola 19 Esercizi Si scriva la funzione cancella per il caso delle liste ordinate (si sfrutti l ordinamento per semplificare la ricerca) Si scriva una funzione cancellatutti che cancella tutte le occorrenze di un dato elemento da una lista Si scriva una funzione cerca che restituisce true se un dato elemento è presente nella lista passata come parametro Si riscrivano le funzioni di inserimento in ordine e cancellazione in forma ricorsiva Informatica A - Cugola 20