APPUNTI SUL LINGUAGGIO C Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Tipi di dato astratto
Tipi di dato Struct (record) Puntatori Liste concatenate
Struct (record) Le strutture sono collezioni di variabili correlate sotto un unico nome. Le strutture possono contenere variabili di diversi tipi di dato (contrariamente ai vettori, che contengono soltanto elementi dello stesso tipo di dato) Le strutture sono un tipo di dato derivato (sono cioè costruite usando oggetti di altri tipi).
Struct (record) Per accedere a un campo del record si usa l’operatore punto. Se abbiamo un puntatore al record possiamo accedere ai sui campi attraverso l’operatore ->. ... struct persona tizio; struct persona *p; struct persona amici[10]; scanf(“%s”, tizio.nome); tizio.eta++; printf(“%s”, amici[3].cognome); p = &tizio; printf(“%s”,p->cognome);
Proprietà dei record È permesso l’autoriferimento mediante i puntatori. struct persona { char nome[20]; char cognome[20]; struct persona *coniuge; } io; struct elemento { int info; struct elemento *next; } lista; Struttura Nidificata
Allocazione dinamica della memoria L'allocazione dinamica della memoria consente una efficace gestione della memoria a tempo di esecuzione. Si usa generalmente per la gestione di dati di cui non è nota a priori la dimensione. In ANSI C ci sono quattro funzioni per gestire dinamicamente la memoria: • malloc • calloc • realloc • free Queste funzioni sono contenute nella libreria: stdlib.h
void *malloc( size_t size ) Alloca in maniera dinamica una zona di memoria della dimensione specificata in numero di byte. Restituisce un puntatore di tipo void all'area di memoria allocata. Se non c'è sufficiente quantità di memoria, restituisce NULL. Si usa in genere insieme alla funzione C sizeof che restituisce la dimensione in numero di byte di una variabile o di un tipo. Viene sempre seguita da una operazione di "casting" per restituire un puntatore del tipo desiderato. void *malloc( size_t size )
Calloc e Realloc void *calloc( size_t n_elem, size_t elem_size ) La calloc alloca in maniera dinamica una zona di memoria per memorizzare n oggetti della dimensione specificata. La realloc rialloca uno spazio di memoria precedentemente allocato con una calloc o malloc (si usa in genere per modificare dimensione e/o tipo di un'area di memoria già allocata). In entrambi i casi viene restituito un puntatore di tipo void all'area di memoria (ri)allocata. Se non c'è sufficiente quantità di memoria, viene restituito NULL. void *calloc( size_t n_elem, size_t elem_size ) void *realloc( void *p, size_t size )
Free void *free( void *p ) Rilascia una zona di memoria precedentemente allocata con una malloc, una calloc o una realloc. N.B.: andrebbe sempre usata prima della fine del programma su ogni variabile allocata dinamicamente. void *free( void *p )
Le Liste Concatenate Una lista concatenata è una collezione lineare di strutture connesse da puntatori, detti link (anelli o collegamenti), da cui il termine concatenata. Elemento Elemento Elemento
Le Liste Concatenate I nodi di una lista sono strutture ricorsive: una struttura contenente un membro di tipo puntatore, che fa riferimento a una struttura dello stesso tipo di quella in cui è contenuto. Elemento
Le Liste Concatenate Ci saranno sue nodi particolari: un puntatore al primo elemento e l’ultimo nodo punterà a NULL. Elemento
Le Liste Concatenate Ci saranno sue nodi particolari: un puntatore al primo elemento e l’ultimo nodo punterà a NULL. NULL Elemento
Le Liste Concatenate /**************** Direttive ***************/ #include <stdio.h> #include <stdlib.h> #define FALSE 0 #define TRUE 1
Le Liste Concatenate /************ Definizione tipi ************/ typedef int tipoelem; typedef struct elem { tipoelem info; struct elem* next; } elist; typedef elist *plist; //typedef < tipo > < nuovo_nome_tipo >;
Le Liste Concatenate elist info plist info
Le Liste Concatenate /*********** Prototipi funzioni ***********/ /*restituisce la lista vuota*/ plist init(); /*verifica se una lista è vuota*/ int empty(plist); /*aggiunge un elemento in testa alla lista e restituisce la lista risultato*/ plist cons(plist, tipoelem); /*stampa tutta la lista*/ void stampa(plist);
Le Liste Concatenate /*********** Prototipi funzioni ***********/ /*restituisce il primo elemento della lista*/ tipoelem car(plist); /*toglie il primo elemento della lista e restituisce la lista risultato*/ plist cdr(plist);
Le Liste Concatenate temp plist init() NULL NULL l ? int empty(plist l)
Le Liste Concatenate /********** Definizione funzioni **********/ plist init() { plist temp; temp = NULL; return(temp); } int empty(plist l) { if (!l) return (TRUE); else return (FALSE);
Le Liste Concatenate plist cons(plist l, tipoelem e) temp l e tipoelem car(plist l) l info
Le Liste Concatenate plist cons(plist l, tipoelem e) { plist temp; temp = (plist)malloc(sizeof(elist)); temp->info = e; temp->next = l; return(temp); } tipoelem car(plist l) { return(l->info);
Le Liste Concatenate plist cdr(plist l) l temp temp l
Le Liste Concatenate plist cdr(plist l) l temp l
Le Liste Concatenate plist cdr(plist l) { plist temp; if (empty(l)) return(l); temp = l; l=l->next; free(temp); return(l); }
Le Liste Concatenate void stampa(plist l) l
Le Liste Concatenate void stampa(plist l) { printf("("); while (l) { printf("%d",l->info); printf(")"); l = l->next; } printf(")\n");
Le Liste Concatenate /********** Programma principale **********/ main() { int scelta; boolean continua=TRUE; tipoelem e; plist l; l=init();
Le Liste Concatenate while (continua) { /**** Stampa Menu Operazioni ****/ printf("--------Menu--------\n"); printf("1) Cons\n"); printf("2) Car\n"); printf("3) Cdr\n"); printf("4) Empty\n"); printf("5) Stampa\n"); printf("6) Esci\n"); printf("Scelta:"); scanf("%d",&scelta);
switch(scelta) { case 1: printf("Elemento:"); scanf("%d",&e); l=cons(l,e); break; case 2: if (empty(l)) printf("Vuota!\n"); else { printf("1^ elemento:"); printf("%d\n",car(l)); } break;
case 3: if (empty(l)) printf("Vuota!\n"); else l=cdr(l); break; case 4: else printf("Piena!\n"); break; case 5: stampa(l); break; default: continua=FALSE; break; }
Le Pile Una pila (o stack) è una versione limitata di una lista concatenata. I nuovi nodi possono essere aggiunti alla pila e rimossi dalla stessa soltanto dalla sua testa. La pila è quindi anche detta struttura LIFO (l’ultimo ad entrare è il primo ad uscire).
Le Pile Da notare che le pile e le liste concatenate sono rappresentate in modo identico. La differenza è che nelle liste il punto di inserimento e di eliminazione potrebbe essere ovunque, mentre in una pila corrisponde sempre alla sua testa. Elemento Elemento Elemento
/**************** Direttive ***************/ #include <stdio.h> #include <stdlib.h> #include "liste.h" #define FALSE 0 #define TRUE 1 /************ Definizione tipi ************/ typedef plist pstack;
/*********** Prototipi funzioni ***********/ /*restituisce la pila vuota*/ pstack initS(); /*verifica se una pila è vuota*/ boolean emptyS(pstack); /*aggiunge un elemento in testa alla pila*/ pstack push(pstack,tipoelem); /*restituisce il primo elemento della pila*/ tipoelem top(pstack); /*toglie il primo elemento della pila*/ pstack pop(pstack); /*stampa tutta la pila*/ void stampaS(pstack);
pstack initS() { return(init()); }; NULL temp NULL
boolean emptyS(pstack S) {return (empty(s));}; NULL NULL S ?
pstack push(pstack s,tipoelem e) { return(cons(s,e)); }; temp s e
tipoelem top(pstack s) { return(car(s)); } info
pstack pop(pstack s) { return(cdr(s)); } l temp l
void stampaS(pstack s) { stampa(s); }
Le Code Una coda (o queue) è simile a una fila ad uno sportello: la prima persona della fila sarà servita per prima, mentre gli altrii vi entreranno solo dalla sua estremità finale e attenderanno di essere serviti. I nodi delle code possono essere rimossi soltanto dalle loro teste e possono essere inseriti soltanto alla fine. Una coda è detta quindi struttura FIFO (il primo ad entrare è il primo ad uscire).
Le Code Una coda è così rappresentata come una lista concatenata ma avrà due punti di accesso (due puntatori): uno in testa e l’altro in coda (fine della lista) per rispettivamente togliere dalla coda e inserire in coda. tail head Elemento Elemento …
Esercizio void InserisciInCoda(plist *l, char n) Proviamo a scrivere un programma che gestisca una lista di caratteri: 1) inserire un carattere in coda. 2 cancella il nodo il cui valore è uguale ad un carattere x da input void InserisciInCoda(plist *l, char n) void CancellaVal(plist *l, char x)
APPUNTI SUL LINGUAGGIO C Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Strutture dati FINE