argomenti (Sezione 9.1 e Capitolo 13 Savitch) puntatori puntatori I PUNTATORI E LE STRUTTURE DATI DINAMICHE 1. dichiarazioni di puntatori

Documenti analoghi
I PUNTATORI E LE STRUTTURE DATI DINAMICHE. Cosimo Laneve/Ivan Lanese

Problemi legati all'uso dei Puntatori

PUNTATORI. Ivan Lanese

Puntatori in C. Fondamenti di Informatica. Daniele Loiacono

Laboratorio di Informatica I

I parametri e il sovraccarico

Operazioni su liste. Creazione della lista (vuota e successivi inserimenti) Lettura di una lista Stampa di una lista Cancellazione di una lista

Strutture dati concatenate

Il linguaggio C. Puntatori e dintorni

Strutture. Array dei nomi degli esami (MAX ESAMI è il massimo numero degli esami). Array con i crediti degli esami.

Laboratorio di algoritmi e strutture dati

Il linguaggio C Strutture

Liste. Marco Alberti Programmazione e Laboratorio, A.A

Laboratorio di Informatica

Esercitazione 11. Liste semplici

Strutture dati dinamiche

Fondamenti di Informatica

Allocazione Dinamica della Memoria

Allocazione dinamica della memoria

Tipi di dato strutturato. Tipi strutturati: il Record. Il Record. Il Record in C: struct

Liste. Una lista è una struttura dati (formata da elementi dello stesso tipo e collegati insieme) la cui lunghezza può variare dinamicamente.

Università degli Studi di Cassino e del Lazio Meridionale Corso di Fondamenti di Informatica Allocazione dinamica di memoria

Programmazione I Prova scritta - 10 gennaio h20min

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Il linguaggio C Strutture

Laboratorio Informatica Classe 4A Serale Venerdì 18/02/2011. Gruppo. Cognome Riontino Nome Raffaele. Cognome Nome

Esercitazioni di Fondamenti di Informatica - Lez. 7 20/11/2018

INFORMATICA A. Titolo presentazione sottotitolo. Laboratorio n 6 Dott. Michele Zanella Ing. Gian Enrico Conti

Variabili e Funzioni. Informatica 1 / 19

LE STRUTTURE. Cosimo Laneve

Strutture Dinamiche. Fondamenti di Informatica

Esercitazioni di Fondamenti di Informatica - Lez. 8 27/11/2018

Liste concatenate e allocazione dinamica

Strutture Dinamiche. Strutture Dinamiche

Gestione dinamica di una lista

La programmazione nel linguaggio C. Liste

cons: L E L (...), e (e,...) Operatori tradizionali sulle liste car: (e,...) cdr: What s LISTE? null: () TRUE (...) FALSE Una lista e' una

Laboratorio di algoritmi e strutture dati

e e n-1 Esercizio 1.2 (Punti 8; punti 10 se risolto facendo uso della ricorsione)

Gestione dinamica di una coda

La struttura dati CODA

Allocazione dinamica della memoria

Variabili dinamiche. Obiettivi: Presentare le variabili dinamiche, allocate e deallocate nell area HEAP, e le funzioni malloc e free

Linked Lists. Liste linkate (1) Progettazione: struct. Liste linkate (2)

Ogni variabile in C è una astrazione di una cella di memoria a cui corrisponde un nome, un contenuto e un indirizzo.

Allocazione dinamica della memoria

Esercizi Strutture dati di tipo astratto

Linguaggio C: Strutture e Liste Concatenate Valeria Cardellini

Scrivere un funzione ricorsiva che stampa a video i valori di una lista di elementi con campo info di tipo intero.

Funzioni, Stack e Visibilità delle Variabili in C

LABORATORIO DI PROGRAMMAZIONE 2 Corso di laurea in matematica. Algoritmi ricorsivi

Strutture dati dinamiche in C. Emilio Di Giacomo

Allocazione dinamica memoria

Strutture Dati per Inserimento Ordinato. Luca Abeni

Linked Lists. Liste linkate (1) liste linkate ( stack, queues ), trees. Liste linkate come strutture

Fondamenti di Informatica e Laboratorio T-AB T-15 Strutture dati

Laboratorio di Programmazione

Politecnico di Milano. Strutture dati dinamiche

Previously on TDP. LISTA rappresentata mediante "struct e puntatori" Cosa e aux? Di che tipo e e cosa contiene?

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Previously on TDP. LISTA rappresentata mediante "struct e puntatori" TipoLista lis. Dichiarare DISEGNARE e. DISEGNARE aux.

Ingegneria Elettronica Ingegneria delle Telecomunicazioni (J-Z) Ing. Antonio Monteleone A.A. 2001/02 3 ciclo

FUNZIONI. attribuire un nome ad un insieme di istruzioni parametrizzare l esecuzione del codice

Una breve introduzione all implementazione in C di algoritmi su grafo

Funzioni, Stack e Visibilità delle Variabili in C

Liste concatenate. Violetta Lonati

Parte 4. Liste. P. Picasso Guernica, AA. 2015/16

Linguaggio C: PUNTATORI

Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE

Le Funzioni in C. Fondamenti di Informatica Anno Accademico 2010/2011. Corso di Laurea in Ingegneria Civile Politecnico di Bari Sede di Foggia

Esercizio 1: funzione con valore di ritorno di tipo puntatore

Scope delle variabili e passaggio parametri. Danilo Ardagna Politecnico di Milano

Gestione dinamica della memoria

Unità Didattica 4 Linguaggio C. Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo.

Sommario. Tipo stringa: string. Tipo stringa: stile C. Tipo stringa Tipo booleano

Parte 3. Puntatori. [S. Dalí The temptation of St. Anthony, 1946] - AA. 2015/16 3.1

Sommario. Le strutture dati elementari per implementare sequenze: Vettori Liste

E12 Esercizi su Strutture dati dinamiche in C

10/10/2016. Caratteristiche degli array. Il tipo RECORD. Il record. LABORATORIO DI PROGRAMMAZIONE 2 Corso di laurea in matematica

Parte 4D. Liste doppie. R. Magritte Transfer, D.1

PROGRAMMAZIONE II canale A-D luglio 2008 TRACCIA DI SOLUZIONE

Fondamenti di Informatica

IMPLEMENTAZIONE CONCATENATE DELLE LISTE

Lista concatenata. Liste. Strutture autoreferenzianti. Strutture autoreferenzianti

Corso di Fondamenti di Informatica

Inserimento in una lista ordinata

La classe std::vector della Standard Template Library del C++

Informatica per Statistica Riassunto della lezioni del 14/11/2012 e 16/11/2012

Assembly (3): le procedure

Le funzioni: dichiarazione, definizione e chiamata Il passaggio degli argomenti per valore e riferimento La funzione main() Le regole di visibilità

Programmazione C. Puntatori Array come puntatori

Transcript:

argomenti (Sezione 9. e Caitolo Savitch). dichiarazioni di untatori I PUNTATORI E LE STRUTTURE DATI DINAMICHE Cosimo Laneve. le oerazione su untatori (NULL, new, delete, &, *). untatori assati come arametri e ritornate come valori di funzioni. esemi/esercizi 5. le strutture dati dinamiche: liste 6. la funzione revert iterativa untatori un untatore è l indirizzo di una locazione di memoria gli indirizzi di memoria ossono essere usati in alternativa alle variabili: se una variabile è memorizzata in locazioni di memoria successive, l indirizzo di memoria della rima locazione uò essere usato in alternativa alla variabile se una variabile è assata er riferimento in una dichiarazione di funzione, uando la funzione viene invocata, si assa l indirizzo del arametro attuale cf. funzione scambia untatori i linguaggi di rogrammazione consentono di definire tii di dato indirizzi di memoria - è ossibile comrendere il significato del assaggio er riferimento - è ossibile imlementare il assaggio er riferimento attraverso il assaggio er valore di un untatore - è ossibile definire e creare strutture dati di dimensioni non note staticamente (cioè definire VARIABILI DINAMICHE)

oerazioni su untatori? oerazioni su untatori? uando si scrive il rogramma non è ossibile saere in uale indirizzo di memoria il dato sarà caricato ossiamo solamente far riferimento agli indirizzi in maniera simbolica, utilizzando identificatori che li raresentano non è ragionevole calcolare indirizzo_var > indirizzo_var è ragionevole calcolare un untatore non unta ad un indirizzo di memoria ualunue, ma solamente a indirizzi che contengono elementi di un certo tio esemi: untatori a interi untatori a caratteri indirizzo_var == indirizzo_var il untatore è un tio di dato arametrico: diende dal oure tio di elementi a cui unta indirizzo_var!= indirizzo_var 5 6 num_ car_ num car a dichiarazioni di untatori oerazioni su untatori er indicare che un identificatore è un untatore a valori di un certo tio, nella dichiarazione, si refigge l identificatore con * esemi: int * ; // è un untatore a interi double *f_ ; int *, n ; l * identifica come untatore // f_ è un untatore a double // è un untatore a interi // n è un intero NULL (untatore vuoto) & (indirizzo di) new (allocazione blocco di memoria) * (dereferenziazione) delete (deallocazione blocco di memoria) 7 8

oerazioni su untatori/null oerazioni su untatori/& la costante NULL raresenta il untatore vuoto l oeratore &, alicato a una lhs-exression, restituisce il suo indirizzo di memoria (che uò essere assegnato a un untatore) la costante NULL ha valore 0 ed è definita in diverse librerie, incluso iostream la costante NULL uò essere assegnata a ualunue untatore esemio: n = 5 ; = &n ; esemi: int * char *, = NULL = NULL r = NULL r ; ; ; if ( == NULL)... ; // ERRORE! r non è un untatore int *, n ; n = 5 ; n n = &n ; n 5 5 è errore fare = &5 o = &(n*5) 9 0 oerazioni su untatori/new gestione della memoria durante l esecuzione roblema: la dichiarazione di untatore alloca solo lo sazio che uò contenere un indirizzo di memoria la memoria (ram) del rogramma è divisa in due arti: stack e hea come fare a far untare il untatore ad una certa area? la funzione new ermette di allocare dinamicamente la memoria er una variabile di tio untatore new rende in inut un tio e restituisce un untatore ad un nuovo blocco di memoria che contiene elementi di uel tio hea è l area di memoria in cui sono allocati nuovi blocchi di memoria (ad esemio, dalla funzione new) stack è l area di memoria in cui vengono allocati i record di attivazione delle funzioni = new int; rogramma area di lavoro del rogramma stack hea int * ; = new int ; new alloca memoria dall hea

variabili dinamiche oerazioni su untatori/* (dereferenziazione) se si esegue come si fa ad accedere alla cella untata da (che è stata allocata dinamicamente)? le celle di memoria allocate con l oeratore new sono chiamate variabili dinamiche l area di memoria er le variabili dinamiche è creata e distrutta mentre il rogramma è in esecuzione l area ci memoria er le altre variabili è creata a temo di comilazione e distrutta uando il rogramma termina int * ; = new int ; serve un oerazione che, reso un untatore, restituisce l indirizzo di memoria er accedere all elemento untato da esso è l oerazione di dereferenziazione * : = new int ; * = 5 ; * = 5 ; 5 il risultato della dereferenziazione è una lhs-exression oerazioni su untatori/esemi aliasing: oerazioni su untatori/delete rima int *, *, x ;... x = ; = &x ; * = ; cout << * << x ; x x delete non fa nulla se il untatore in inut è NULL esemio: x x * = * ; 5 delete num ; differenza tra oggetti untati e untatori: = ; uest area otrà essere riutilizzate da successive chiamate a new doo = ; * = ; cout << * << x ; rima aliasing tra untatori: delete libera l area di memoria untata dall argomento che deve essere un untatore doo il contenuto della locazione a cui fa riferimento viene aggiornato con il contenuto della locazione a cui fa riferimento hea hea num num A delete num ; 6

dangling ointers il valore del untatore doo l invocazione di delete è indefinito (il valore diende dal comilatore) dangling ointer dangling ointers = ; delete ; * = * + ; se un altro untatore unta alla stessa area di memoria, anche il suo valore è indefinito delete non fa nulla se il untatore in inut è NULL dereferenziare un dangling ointer è una oerazione disastrosa 5 = ; delete ; 5 5 esemio: = ; delete ; * = * + ; ERRORE ERRORE 7 8 oerazioni su untatori/delete regola di rogrammazione: è buona norma riassegnare il untatore doo l invocazione di delete (riassegnare i dangling ointer) definizione di nuovi tii è ossibile definire nuovi tii ed associargli un nome - la arola chiave è tyedef esemi: = ; delete ; = NULL ; = new int ; * = ; int * ; while (true) { = new int ; delete ; // non termina 9 sintassi: tyedef Tio_Noto identificatore ; Tio_Noto è un tio già definito esemi: tyedef int array_di_int[50] ; tyedef int altro_int ; 0

definizione di tii untatori esercizi base su untatori er evitare errori con l uso dei untatori, conviene definire tii untatori esemio: tyedef int* _int ;. definire una variabile di tio intero, incrementarla due volte attraverso due untatori distinti e stamare il risultato - definisce un tio untatore a interi - è ossibile dichiarare variabili di tio _int notare la osi- ad esemio _int ; - è euivalente a int * ; zione dell * - evita confusioni tra untatori a interi e variabili intere nelle dichiarazioni int *, *, x, y; _int, ; int x, y ;. allocare una variabile di tio intero, incrementarla attraverso untatore, stamare il risultato e deallocarla. rendere in inut 0 interi e memorizzarli in un array di 0 interi utilizzando i untatori (le lhs degli assegnamenti sono semre oerazioni *). Poi stamare i valori. definire una struttura di 5 cami interi e memorizzarci 5 interi resi in inut utilizzando i untatori (le lhs degli assegnamenti sono semre oerazioni *). Poi stamare i valori 5. definire una variante della funzione scambia che scambia i valori di due variabili utilizzando i untatori e usarla all interno del main 6. (er casa) ridefinire un algoritmo di ordinamento di array accedendo agli elementi attraverso untatori untatori assati come argomento di funzioni il arametro formale è di tio untatore il arametro attuale è l indirizzo di una variabile untatori assati come argomento di funzioni uot uot division(0,,&uot,&rem); rem esemio: funzione che rende in inut dividendo e divisore, e restituisce uoziente e resto void division(int dvd, int dvs, int *, int *r){ * = dvd / dvs ; *r = dvd % dvs; int main(){ int uot, rem; division(0,, &uot, &rem); cout << uot << rem ; return(0) ; cosa stama main? uot rem dvd 0 dvs * = /d dvd vs; vd = d *r %dv rem s; dvd 0 dvs r uot rem r il assaggio dei untatori è er valore: vengono coiati gli indirizzi che consentono di modificare le variabili del chiamante

esemio/la funzione scambia le strutture dati dinamiche siano a e b di tio int void scambia(int x, int y){ int tm ; tm = x ; x = y ; y = tm ; // invocata con scambia(a,b) void scambia(int *x, int *y){ int tm ; tm = *x ; *x = *y ; *y = tm ; // invocata con scambia(&a,&b) void scambia(int& x, int& y){ int tm ; tm = x ; x = y ; y = tm ; // invocata con scambia(a,b) le strutture dati dinamiche sono strutture dati le cui dimensioni ossono essere estese o ridotte durante l esecuzione del rogramma tutti i tii di dati studiati finora hanno una dimensione che è nota staticamente ci sono casi in cui sono necessari dati la cui dimensione è sconosciuta al rogrammatore void scambia(int *x, int *y){ int *tm ; tm = x ; x = y ; y = tm ; // invocata 5 con scambia(&a,&b) 6 esemi di strutture dati dinamiche seuenza di caratteri lunga a iacere da rendere in inut e da stamare in modo invertito numeri naturali grandi a iacere e oerazioni su di esse ile, code, insiemi senza limitazioni sul numero di elementi uesti roblemi ossono essere risolti con gli array, MA IN MODO INSODDISFACENTE tii di dato dinamici/le liste una lista è una seuenza di nodi che contengono valori (di un determinato tio) e in cui ogni nodo, eccetto l ultimo, è collegato al nodo successivo mediante un untatore una lista cresce/decresce durante l esecuzione una lista è di solito una struttura con un camo che contiene un untatore alla struttura stessa di solito la lista viene visualizzata attraverso nodi e frecce che li connettono 7 8

imlementazione dei nodi i nodi i rettangoli in blu del disegno raresentano i nodi della lista i nodi contengono le informazioni memorizzate nella lista e un untatore i nodi sono imlementati in C++ mediante tii di dato struct (o mediante classi... ) esemio: una struttura che memorizza due elementi un intero e un untatore ai nodi della struttura il untatore unta all intero nodo, non ad una arte di esso il untatore struct lista { int val ; lista *next ; ; raresenta NULL 9 0 la testa della lista uesta definizione circolare è ammessa in C++ accesso agli elementi della lista il rettangolo chiamato non è un nodo della lista ma un untatore ad essa uesto è un modo er modificare l intero nel rimo nodo da a 5 (*).val = 5 ; - è dichiarato lista * ; - oure è ossibile definire un tio di dato untatore alla lista e dichiararlo di conseguenza tyedef lista* tr_lista ; tr_lista ; - è di tio untatore, uindi * restituisce l oggetto untato (dereferenziazione) - l oggetto untato è una struttura e si utilizza la dot-notation er accedere al camo val - le arentesi sono necessarie erchè il. ha recedenza sul *

l oeratore freccia (->) come creare una lista iniziamo con la definizione: l oeratore -> combina le azioni della dereferenziazione e dell accesso a un camo di una struttura (*).val = 5 ; struct lista { int val ; lista *next ; ; tyedef lista* tr_lista ; uindi definiamo la testa della lista tr_lista ; uò essere riscritto uindi creiamo il rimo nodo = new lista ; ->val = 5 ; - ora unta al rimo e unico nodo della lista - l oeratore -> è uello iù usato come creare una lista oerazioni su liste dichiarazioni e inizializzazioni ora che unta ad un nodo occorre inizializzare i cami con dei valori ->val = 5 ; ->next = NULL ; 5 oichè uesto è l unico nodo, il untatore al resto della lista è inizializzato a NULL tr_lista,, ;?? = new lista ; ->val = ;?? = new lista ; ->val = ; = ; collegamento tra nodi?? ->next = ; tre modi er accedere al camo val del secondo nodo ->val ->val 5 (->next)->val oure oure oure 6 (*).val (*).val (*((*).next)).val

oerazioni su liste oerazioni su liste aggiunta di un nodo in coda ->next = new lista ; (->next)->val = ;???? - cosa succede se facessi = new lista ; la testa è il rimo elemento della lista ultimo elemento della lista: si memorizza nel camo next il valore NULL (->next)->next = NULL; la variabile unta alla testa della lista una funzione che conosce l indirizzo contenuto in ha accesso ad ogni elemento della lista 7 8 inserimento di nodi inserimento di un elemento tra rimo e secondo 0 inserimento di un elemento in testa: = new lista ; ->val = 0 ; ->next = ; = ; inserimento di un elemento tra il rimo e il secondo = new lista ; ->val = ; ->next = ->next ; ->next = ; 0 l inserimento di un elemento tra rimo e secondo richiede la modifica SOLAMENTE di due untatori nelle liste - ciò vale ualunue sia la lunghezza della lista - se avessimo avuto un array, avremmo dovuto sostare tutti gli elementi er far osto al nuovo elemento - inserire in una lista è iù efficiente che inserire in un array 9 0

la funzione _insert (seudo-)codice er _insert - creare una nuova variabile dinamica untata da tm_ rogettiamo una funzione che rende una lista ed un elemento e ritorna la lista con il nuovo elemento in testa: - la dichiarazione della funzione è tr_lista _insert (tr_lista, int el) ; - _insert creerà un nuovo nodo che conterrà el nel camo val - inizializzare il nuovo nodo *tm_ con el e con - ritornare il untatore tm_ il codice tr_lista _insert (tr_lista, int el){ tr_lista tm_ ; tm_ = new lista ; tm_->val = el ; tm_->next = ; return(tm_) ; lista vuota erdere nodi - una lista senza elementi è detta lista vuota - una lista vuota non ha un nodo in testa - il untatore alla lista vuota ha valore NULL - una funzione che oera sulle liste deve SEMPRE essere verificata uando l inut è una lista vuota - _insert è corretta uando == NULL si otrebbe ensare di definire _insert in uesto modo tr_lista _insert (tr_lista, int el){ = new lista ; il vecchio nodo a cui ->val = el ; ->next = ; untava è erso return() ; ritorna una lista circolare

erdita di nodi altri esemi memory leaks rimozione dell elemento di testa: 0 = ->next ; il rimo elemento è erso se non è untato da un altro untatore... i nodi che sono ersi assegnando i loro untatori a nuovi indirizzi non sono iù accessibili non c è alcun modo er fare riferimento ai nodi ersi e er recuerare la loro memoria nell hea libero un rogramma che erde nodi ha un memory leak rimozione del secondo elemento: ->next = (->next)->next ; 0 il secondo elemento è erso se non è untato da un altro untatore... - rogrammi con memory leaks significativi ossono causare crash di sistema - esemio: while (true) { = new int ; // termina con out-of-memory 5 6 ricerca di elementi in una lista rimo codice er la ricerca di elementi in una lista ermette di visitare l elemento successivo della lista tr_lista search_el(tr_lista, const int e) ; oichè il untatore è assato er valore, ossiamo scorrere la lista utilizzando - si uò evitare di dichiarare un untatore locale alla funzione l algoritmo è di scorrere la lista untata da finchè non si trova l elemento e oure il valore di è NULL - l oerazione er scorrere la lista è - in ogni caso la funzione ritorna 7 = ->next ; tr_lista search_el(tr_lista, const int e){ while ((->val!= e)&&(->next!= NULL)) = ->next ; if (->val == e) return() ; else return(null) ;. controllare il caso in cui l elemento e si trova come ultimo. controllare il caso in cui è NULL 8

rimo codice er la ricerca di elementi in una lista secondo codice er la ricerca di elementi in una lista la funzione tr_lista search_el(tr_lista, const int e){ while ((->val!= e)&&(->next!= NULL)) = ->next ; if (->val == e) return() ; else return(null) ; ha un errore uando == NULL - bisogna ensare a un caso seciale uando è NULL tr_lista search_el(tr_lista, const int e){ if ( == NULL) return(null) ; else { while ((->val!= e)&&(->next!= NULL)) = ->next ; if (->val == e) return() ; else return(null) ; - funziona ma ha l aria di essere un atch 9 50 terzo codice er la ricerca di elementi in una lista tr_lista search_el(tr_lista, const int e){ bool found = false ; while ((!= NULL) && (!found)){ if (->val == e) found = true ; else = ->next ; return() ; 5 non è ossibile imlementare la ricerca binaria untatori e iteratori un iteratore è un oeratore che consente di eseguire la stessa azione su ogni elementi di un tio di dato comlesso un iteratore si uò alicare - ad un array, mediante l indice - o ad una lista, mediante il untatore alla testa un attern generale di iteratore er liste è node *iter = ; while (iter!= NULL){ // esegui l azione sul nodo untato da iter iter = iter->next ; unta al nodo iniziale della lista 5

esemio di iteratore: stama degli elementi in una lista inserimento in coda inserimento di un elemento in coda a una lista: void stama_el(tr_lista ){ tr_lista iter = ; while (iter!= NULL) { cout << iter->val ; iter = iter->next ; = ; while (!= NULL) = ->next ; = new lista ; ->val = 0 ; ->next = NULL ; erchè è sbagliato? in alternativa al attern recedente si uò usare node *iter ; for(iter = ; iter!= NULL; iter = iter->next){ // esegui l azione sul nodo untato da iter 0 il nodo untato da è scollegato dalla lista! 5 5 inserimento in coda inserimento in coda iteriamo su ->next : = ; while (->next!= NULL) = ->next ; ->next = new lista ; = ->next ; ->val = 0 ; ->next = NULL ; ha un errore uando 0 == NULL - bisogna ensare a un caso seciale uando è NULL 55 if ( == NULL) { = new lista ; ->val = 0 ; ->next = NULL ; else { = ; while (->next!= NULL) = ->next ; ->next = new lista ; = ->next ; ->val = 0 ; ->next = NULL ; 56

rimozione dalla coda rimozione dalla coda vogliamo rimuovere l ultimo elemento della lista erchè è sbagliato scrivere - la lista deve avere almeno un elemento, altrimenti non c è niente da rimuovere erchè è sbagliato scrivere = ; while (->next!= NULL) = ->next ; delete ; = NULL ; è un dangling ointer! = ; while (->next!= NULL) = ->next ; delete ->next ; ->next è già NULL ->next = NULL ; delete ->next non fa niente (vedi lucido relativo) 57 58 rimozione dalla coda rimozione dalla coda dobbiamo iterare su ->next->next in alternativa ad usare ->next->next che è oco leggibile, si ossono usare due untatori: e after dobbiamo searare i casi di lista con un solo elemento da uelli di lista con almeno due elementi if (->next == NULL) { delete ; = NULL ; else { = ; while (->next->next!= NULL) = ->next ; delete ->next ; ->next = NULL ; uesto codice va eseguito solamente se la lista untata da ha almeno un elemento 59 - after unta al nodo successivo a if (->next == NULL) { delete ; = NULL ; else { = ; after = ->next ; while (after->next!= NULL) { = after ; after = after->next ; delete after ; ->next = NULL ; 60

esercizi sulle liste. scrivere un rogramma che crea una lista di lunghezza length (costante) i cui elementi sono numeri generati casualmente, li inserisce in una lista e oi stama la lista degli inut stama il valore iù vicino alla media. scrivere un rogramma che rende in inut interi dall utente finchè l utente non inserisce 0, oi rende un altro intero n e rimuove dalla lista tutti gli interi multili di n, uindi stama la lista. scrivere un rogramma che consente all'utente di lavorare su una lista di interi con le seguenti oerazioni aggiungere un elemento in fondo vedere le informazioni dell'elemento corrente andare avanti di uno andare indietro di uno eliminare l'elemento corrente 6 le liste/revert roblema: scrivere una funzione che rende in inut una seuenza di caratteri che termina con il. e stama la seuenza invertita void revert(){ char c ; tr_lista, ; = NULL ; cin >> c ; while (c!= '.') { = new lista ; ->val = c ; ->next = ; = ; cin >> c ; 6 costruisce una ila cout << "\n la seuenza invertita e`: " ; while (!= NULL){ cout << ->val ; = ->next ; strutture dati dinamiche/esercizi. imlementare il tio di dato ila con le oerazioni di (a) creazione della ila vuota, (b) ush = inserimento di un elemento nella ila, (c) o = eliminazione di un elemento dalla ila; (d) to = valore dell elemento in testa alla ila. imlementare il tio di dato coda con le oerazioni di (a) creazione della coda vuota, (b) enueue = inserimento di un elemento nella coda, (c) deueue = eliminazione di un elemento dalla testa della coda; (d) to_el = valore dell elemento in testa alla coda. imlementare il tio di dato insieme con le oerazioni di (a) creazione dell insieme vuoto, (b) is_in = aartenenza di un elemento all insieme (c) union = unione di due insiemi; (d) intersection = intersezione di due insiemi 6 liste bidirezionali alcune delle oerazioni recedenti sono scomode da imlementare su liste semlici ossiamo modificare leggermente la struttura dati lista er risolvere roblemi uali accesso all'ultimo elemento nelle liste semlici è necessario scorrere tutta la lista è sufficiente tenere in una variabile il untatore all'ultimo elemento della lista sostamento all'indietro nelle liste semlici è necessario scorrere tutta la lista cercando l'elemento che unta a uello corrente è sufficiente tenere in ogni elemento un untatore al recedente nel rimo elemento uesto untatore avrà valore NULL ueste liste si chiamano liste bidirezionali o con doi untatori 6

lista bidirezionali definizione in C++ struct bilista { int val; bilista *rec ; bilista *next ; ; tyedef bilista* tr_bilista ; tail liste bidirezionali: esercizi rendere in inut caratteri e creare una lista bidirezionale che li contenga. Stamare i caratteri inseriti in ordine inverso e in ordine normale scrivere un rogramma che consente all'utente di lavorare su una lista bidirezionale di interi con le seguenti oerazioni aggiungere un elemento in fondo vedere le informazioni dell'elemento corrente andare avanti di uno andare indietro di uno eliminare l'elemento corrente 65 66