Laboratorio di Programmazione (Laurea triennale in matematica) Lezione 21
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
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
Le liste in C Sono le strutture dinamiche più semplici Una lista è composta da un insieme di nodi Ciascun nodo contiene: Un dato Il puntatore al nodo successivo
Le liste in C struct nodo { int info; struct nodo *next; ; typedef struct nodo Nodo; typedef Nodo *PNodo;
Presentiamo le principali funzioni di gestione delle liste. Di ogni funzione presentiamo: una versione che restituisce void e quindi passiamo la lista per riferimento = doppio puntatore a nodo una versione alternativa che restituisce la lista (puntatore a nodo) e quindi passiamo la lista per valore = puntatore a nodo
Inizializzazione void inizializza(pnodo *l) { *l = NULL; Esempio nel main Pnodo lista;... inizializza(&lista );
Inizializzazione (alternativa) PNodo inizializzaa() { return NULL; Esempio nel main Pnodo lista;... lista = inizializzaa();
Controllo lista vuota int listavuota(pnodo l) { return l == NULL; Esempio nel main Pnodo lista;... if(listavuota(lista)) {...
Stampa di una lista void stampa_lista(pnodo p) { while (p!= NULL) { printf("%d --> ", p->info); p = p->next; printf("null\n"); Esempio output: 5 --> 23 --> 34 --> NULL;
Inserimento in testa void inserisciintesta(pnodo *l, int el){ PNodo temp; temp = (PNodo) malloc(sizeof(nodo)); temp->info = el; temp->next = *l; *l=temp; Esempio nel main Pnodo lista;... int i1, i2;... inserisciintesta(&lista, i1); inserisciintesta(&lista, i2);
Inserimento in testa (alternativa) PNodo inserisciintestaa(pnodo l, int el){ Nodo *temp; temp = (PNodo) malloc(sizeof(nodo)); temp ->info = el; temp ->next = l; return temp; Esempio nel main Pnodo lista;... int i1, i2;... lista = inserisciintestaa(lista, i1); lista = inserisciintestaa(lista, i2);
Inserimento in testa 2 void inserisciintesta2(pnodo *l, int el){ // versione con controllo disponibilità memoria Nodo *temp; temp = (PNodo) malloc(sizeof(nodo)); if (temp!= NULL) { temp->info = el; temp->next = *l; *l=temp; else printf("memoria esaurita!\n"); NOTA: controllo se malloc ha "trovato" memoria disponibile...
Inserimento in coda void inserisciincoda(pnodo *l, int el) { Nodo *temp, *p; temp = (PNodo) malloc(sizeof(nodo)); temp->info = el; temp->next = NULL; if (listavuota(*l)) *l= temp; else { p=*l; while(p->next!=null) // scorro fino alla fine p=p->next ; p->next=temp;
Inserimento in coda 2 void inserisciincoda2(pnodo *l, int el) {Nodo *p; if (listavuota(*l)) { *l = (PNodo) malloc(sizeof(nodo)); (*l)->info = el; (*l)->next = NULL; else { p=*l; while(p->next!=null) // scorro fino alla fine p=p->next ; p->next = (PNodo)malloc(sizeof(Nodo)); p->next->info = el; p->next->next = NULL;
Inserimento in coda alternativo PNodo inserisciincodaa(pnodo l, int el) { Nodo *temp, *p; temp = (PNodo) malloc(sizeof(nodo)); temp->info = el; temp->next = NULL; if (listavuota(l)) return temp; else { p=l; while(p->next!=null) p=p->next ; p->next=temp; return l;
Ins. in coda ricorsivo void inserisciincodaricors(pnodo *l, int el) {//inserimento alla fine della lista in versione ricorsiva if (listavuota(*l)) { *l = (PNodo) malloc(sizeof(nodo)); (*l)->info = el; (*l)->next = NULL; else inserisciincodaricors( &((*l)->next), el);
Ins. in coda ricorsivo alternativo PNodo inserisciincodaaricors(pnodo l, int el) { Nodo *temp; if (listavuota(l)) { temp = (PNodo) malloc(sizeof(nodo)); temp->info = el; temp->next = NULL; return temp; else { l->next = inserisciincodaaricors(l->next, el); return l;
Cancellazione di un elemento int cancella(pnodo *l, int val) { PNodo temp, q1,q2; if (val == (*l)->info) { //se val è nel primo nodo temp = *l; *l = (*l)->next; free(temp); /* libero la memoria return 1; else // val non era il primo nodo {...(continua )
else // val non era il primo nodo { q1= *l; q2= q1->next; while ( (q2!=null) &&(q2->info!= val) ){ //vado avanti finche' trovo la posizione o fine lista q1= q2; q2= q1->next; if (q2!=null){ // ho trovato val temp = q2; q1->next = q2->next; free(temp); /* libero la memoria return 1; else return 0; //non ho trovato val
Cancell. di un elemento alternativo PNodo cancellaa(pnodo l, int el) { Nodo *temp, *puntcorr, *puntprec ; if(listavuota(l)) return l; if(l->info==el) { //devo cancellare il primo elemento temp = l; l = l->next; free(temp); else { //non cancello il primo elemento (continua...)
else { //non cancello il primo elemento puntprec=null; puntcorr =l; while( puntcorr!=null && puntcorr->info!=el){ puntprec = puntcorr; puntcorr=puntcorr->next; if(puntcorr!=null && puntcorr->info==el) { temp=puntcorr; puntprec->next = puntcorr->next; free(temp); return l;
Esercizi Es1: Si scriva una funzione cancellatutti che cancella tutte le occorrenze di un dato elemento da una lista Es2: Si scriva una funzione cerca che restituisce true se un dato elemento è presente nella lista passata come parametro Es3. Si scriva una funzione cancelladuplicatiche cancella tutte le occorrenze ripetute di ogni elemento da una lista (alla fine nella lista dovranno esserci tutti elementi distinti)
The end