i puntatori e le strutture dati dinamichelaneve/html/linguaggi/lez9-dinamiche.pdf · slide 3...

32
I PUNTATORI E LE STRUTTURE DATI DINAMICHE Cosimo Laneve/Ivan Lanese

Upload: nguyenbao

Post on 15-Feb-2019

217 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

I PUNTATORI E LE STRUTTURE DATI DINAMICHE

Cosimo Laneve/Ivan Lanese

Page 2: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 2

argomenti

1. dichiarazioni di puntatori

2. le operazione su puntatori (NULL, new, delete, &, *)

3. puntatori passati come parametri e ritornate come valori di funzioni

4. esempi/esercizi

5. le strutture dati dinamiche: liste

6. la funzione revert iterativa

Page 3: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 3

prologo

le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere estese oridotte durante l’esecuzione del programma

– tutti i tipi di dati studiati finora hanno una dimensione che è nota staticamente

– ci sono casi in cui sono necessari dati la cui dimensione è sconosciuta al programmatore

esempi:

– sequenza di caratteri da scrivere in modo invertito (sappiamo risolverlo solo con laricorsione)

– numeri naturali grandi a piacere e operazioni su di esse

– pile, code, insiemi senza limitazioni sul numero di elementi

– alberi genealogici di famiglie e programmi che stampano la lista di avi di date persone(questi alberi aumentano col tempo man mano che nascono nuovi discendenti)

questi problemi possono essere risolti con gli array, ma in modo insoddisfacente

Page 4: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 4

prologo/cont

non è possibile pensare di avere le strutture dati dinamiche in C++ come primitive, vistoche sono infinite

piuttosto bisogna individuare una operazione di base per implementare i tipi di dato dinamicia programma

esempio: una pila può essere implementata in diversi modi

[ci sono degli archi]

oppip

o p p i p

o p p i p

p o i p p

Page 5: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 5

prologo/cont

un arco significa che un elemento è logicamente connesso con un altroelemento

– occorre definire questa connessione logica per implementare i tipi di dato dinamici

nella memoria ciò che accade è:

gli elementi sono strutture con due campi: uno di essi contiene il valoredell’elemento, l’altro contiene l’indirizzo di memoria in cui si trova l’elementologicamente connesso

programma

o

p

p

ip

connessioni logiche

programma

p

p

p

i

o

5C3

1BA

7E0

5C

1BA

0FA

7E0

5C

connessioni fisiche(in rosso sono rappresentati gli indirizzi di memoria)

5C3

Page 6: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 6

programma

p

p

p

i

o

5C3

1BA

7E0

5C

1BA

0FA

7E0

5C

5C3

puntatori

quando si scrive il programma non è possibile sapere in quale indirizzo dimemoria il dato sarà caricato

– possiamo solamente far riferimento agli indirizzi in maniera simbolica, utilizzando nomiche li rappresentano

– al momento non abbiamo ancora nessun tipo di dato “indirizzo di memoria”

– abbiamo utilizzato il concetto di “indirizzo di memoria” nel passaggio per riferimento-- vedi funzione scambia

graficamente, anzichè scrivere indirizzi, scriveremo delle frecce, per indicare che un certocontenitore (una variabile) contiene l’indirizzo di memoria di un dato:

p

p

p

i

o

programma

no si

Page 7: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 7

puntatori/cont.

definizione (informale): il tipo di dato “indirizzo di memoria” è dettopuntatore

– un puntatore non punta ad un indirizzo di memoria qualunque, masolamente a indirizzi che contengono elementi di un certo tipo

esempi: puntatori a interi

puntatori a caratteri

puntatori a strutture (liste/pile/code)

osservazione: il puntatore è un tipo di dato parametrico: dipende dal tipo di elementi acui punta

num_p num

3

car_p cara

struct_p struct

a

Page 8: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 8

dichiarazioni di puntatori

per indicare che un identificatore è un puntatore a valori di un certo tipo,

nella dichiarazione, si prefigge l’identificatore con “*”

esempi: int *p ; // p è un puntatore a interidouble *f_p ; // f_p è un puntatore a floatstruct lista {

int val ;struct lista *next ;

} // next è un puntatore

// a strutture lista

Page 9: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 9

operazioni su puntatori

– NULL (puntatore vuoto)

– new (allocazione blocco di memoria)

– delete (deallocazione blocco di memoria)

– & (indirizzo di)

– * (dereferenziazione)

Page 10: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 10

operazioni su puntatori/NULL

la costante NULL rappresenta il puntatore vuoto– di solito si usa come il puntatore memorizzato nell’elemento finale di un

struttura dati dinamica– un programma attraversa una lista, visitando ciascun elemento attraverso

puntatori successivi; quando si ottiene il puntatore NULL significa che è stataraggiunta la fine della lista

la costante NULL può essere assegnata a qualunque puntatore

esempi: int *p

char *q, r ;p = NULL ;q = NULL ; if (p == NULL) . . .r = NULL ; // ERRORE! r non è un puntatore

la costante NULL ha valore 0 ed è definita in diverse librerie, incluso iostream

Page 11: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 11

operazioni su puntatori/new

problema: la dichiarazione di puntatore alloca solo lo spazio che puòcontenere un indirizzo di memoria

– come fare a far puntare il puntatore ad una certa area?

la funzione new permette di allocare dinamicamente la memoria per unavariabile di tipo puntatore

– new prende in input un tipo e restituisce un puntatore ad un nuovo blocco di memoriache contiene elementi di quel tipo

le celle di memoria create usando l’operatore new sono dette dinamiche

– le celle di memoria dinamiche sono create (e distrutte) quando il programma è inesecuzione

nump nump

int *nump ; nump = new int ;

Page 12: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 12

operazioni su puntatori/delete

delete libera l’area di memoria puntata dall’argomento che deve essere un puntatore

– tali celle potranno così essere riutilizzate da successive chiamate a new– il valore del puntatore dopo l’invocazione di free è indefinito (dipende dal

compilatore) -- dangling pointer

– delete non fa nulla se il puntatore in input è NULL

esempio: delete nump ;

regola di programmazione: è buona norma riassegnare il puntatore dopo l’invocazione didelete (riassegnare i dangling pointer)

esempi: int *p ;while (true) { p = new int ; delete p ; } // non terminawhile (true) { p = new int ; } // termina con out-of memory

nump Adelete nump ;

heap

nump

heap

Page 13: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 13

gestione della memoria durante l’esecuzione

la memoria (ram) del programma è divisa in due parti: stack e heap– heap è l’area di memoria in cui sono allocati nuovi blocchi di memoria (ad esempio, dalla

funzione new)

– stack è l’area di memoria in cui vengono allocati i record di attivazione delle funzioni

new alloca memoria dall’heap, delete libera la memoria dell’heap

programma

stack

heap

identificatori globali

Page 14: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 14

operazioni su puntatori/&

l’operatore &, applicato a una lhs-expression, restituisce il suo indirizzo dimemoria (che può essere assegnato a un puntatore)esempio: int *p, n ;

n = 5 ;p = &n ;

[è errore fare p = &5 o persino p = &(n*5) ]

esempio: struct lista *p, qq.val = 3 ; q.next = NULL ;p = &q ;

p

n

n = 5 ; p

n

p = &n ;

5 5

p

n

33

p

q q q

p pq.val = 3 ; q.next = NULL; p = & q ;

Page 15: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 15

operazioni su puntatori/* (dereferenziazione)

se si esegueint *nump ;newp = new int ;

come si fa ad accedere alla cella puntata da newp (che è stata allocatadinamicamente)?

– serve un operazione che, preso un puntatore, restituisce l’indirizzo di memoria peraccedere all’elemento puntato da esso

– il risultato di questa operazione deve essere una lhs-expression

è l’operazione di dereferenziazione “*”

esempio: *p = 5 ;

p newp = new int; p *p = 5;

5

p

Page 16: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 16

operazioni su puntatori/esempi

esempio (aliasing):int *nump, *numq, x ;x = 1 ;nump = &x ;*nump = 2 ;cout << *nump << x ;

esempio (aliasing tra puntatori):numq = nump ;*numq = 1 ;cout << *nump << x ;

esempio (differenza tra oggetti puntati e puntatori):numq = nump ; // cambia la locazione a cui

// punta numq*numq = *nump ; // cambia il contenuto della

// locazione a cui punta numq

Page 17: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 17

esercizi base su puntatori

• definire una variabile di tipo intero, incrementarla due volte attraverso due puntatori distinti e stampare il risultato

• allocare una variabile di tipo intero, incrementarla, stampare il risultato e deallocarla

Page 18: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 18

puntatori passati come argomento di funzioni

il parametro formale è un oggetto di tipo puntatore il parametro attuale è l’indirizzo di una variabile

esempio: funzione che prende in input dividendo e divisore, e restituiscequoziente e resto

void division(int dvd, int dvs, int *q, int *r){ *q = dvd / dvs ; *r = dvd % dvs;

}main(void){

int quot, rem; division(10, 3, &quot, &rem);

cout << quot << rem ;}

cosa stampa main?

Page 19: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 19

puntatori passati come argomento di funzioni

quotrem

division(10, 3, &quot, &rem);quotrem

dvd

qdvs

r

310

*q = dvd/dvs; *r = dvd%dvs;

quotrem

dvd

qdvs

r

310

31

quotrem

31

il passaggio dei parametri è pervalore, ma vengono copiati ipuntatori che consentono dimodificare le variabili delchiamante

Page 20: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 20

esempio/la funzione scambia

siano a e b di tipo int

void scambia(int x, int y){int tmp ; tmp = x ; x = y ; y = tmp ;

} // invocata con scambia(a,b)

void scambia(int *x, int *y){int tmp ; tmp = *x ; *x = *y ; *y = tmp ;

} // invocata con scambia(&a,&b)

void scambia(int& x, int& y){int tmp ; tmp = x ; x = y ; y = tmp ;

} // invocata con scambia(a,b)

void scambia(int *x, int *y){int *tmp ; tmp = x ; x = y ; y = tmp ;

} // invocata con scambia(&a,&b)

Page 21: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 21

tipi di dato astratto/le liste

una lista è una sequenza di nodi che contengono dei valori (di undeterminato tipo) e in cui ogni nodo, eccetto l’ultimo, è collegato al nodosuccessivo mediante un puntatore

dichiarazione di lista in C++

struct lista { int val; lista *next;

} ;

aheadval next

b f

Page 22: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 22

tipi di dato astratto/le liste/operazioni

dichiarazioni e inizializzazioni

lista *p1, *p2, *p3 ;

p1 = new lista ;

(*p1).val = 1 ;

p2 = new lista ;

(*p2).val = 2 ;

p3 = p2 ;

collegamento tra nodi

(*p1).next = p2 ;

tre modi per accedere al campo val del secondo nodo (*p2).val

(*p3).val(*((*p1).next)).val

abbreviazione: in alternativa a scrivere (*p1).next si può scrivere p1->next

??1 p1

??2 p2

p3

1 p1

??2 p2

p3

Page 23: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 23

tipi di dato astratto/le liste/operazioni

aggiunta di un nodo in coda

p2->next = new lista ;(p2->next)->val = 3 ;

ultimo elemento della lista: si memorizza nel campo next il valore NULL

(p2->next)->next = NULL;

accesso agli elementi della lista: la testa è il primo elemento della lista

– la variabile p1 punta alla testa della lista

– una funzione che conosce l’indirizzo contenuto in p1 ha accesso ad ogni elementodella lista

1 p1

2 p2

p3 ??3

1 p1

2 p2

p3 3

Page 24: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 24

tipi di dato astratto/le liste/inserimento e rimoz.

le liste (come tutte le strutture dinamiche) sono facilmente modificabili

inserimento di un elemento in testa:

p2 = new lista ;p2->val = 0 ;p2->next = p1 ;p1 = p2 ;

inserimento di un elemento tra il primo e il secondo

p2 = new lista ;p2->val = 4 ;p2->next = (p1->next)->next ;p1->next = p2 ;

rimozione dell’elemento di testa: p1 = p1->next ;

rimozione del secondo elmento: p1->next = (p1->next)->next ;

p2

p3

p1

1

2

3

0

p2

p3

1

2

3

4

p1 0

Page 25: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 25

tipi di dato astratto/le liste/inserimento e rimoz.

inserimento di un elemento in coda:

while (p1->next != NULL) // p1 punta a una lista non vuotap1 = p1->next ;

p1->next = new lista ;p1 = p1->next ;p1->val = 10 ;p1->next = NULL ; // p1 non punta più all’inizio della lista!

domanda: perche` non si è scritto while (p1 != NULL) p1 = p1->next ;

rimozione di un elemento dalla coda

while (p1->next != NULL) // p1 punta a una lista non vuotap1 = p1->next ;

delete p1->next ; p1->next = NULL;

// NON FUNZIONA! Perché?

Page 26: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 26

esercizi sulle liste

• scrivere un programma che prende in input interi dall'utente finchè l'utente noninserisce 0, li inserisce in una lista e poi

– stampa la lista degli input– stampa il valore più vicino alla media

• scrivere un programma che prende in input interi dall’utente finchè l’utente noninserisce 0, poi prende un’ altro intero n e rimuove dalla lista tutti gli interi multipli din, quindi stampa la lista

• scrivere un programma che consente all'utente di lavorare su una lista di interi con leseguenti operazioni

– aggiungere un elemento in fondo– vedere le informazioni dell'elemento corrente– andare avanti di uno– andare indietro di uno– eliminare l'elemento corrente

Page 27: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 27

tipi di dato astratto/le liste/stampa e ricercastampa degli elementi memorizzati in una lista:

void stampa_el(lista *p){ // versione ricorsivaif (p != NULL) {

cout << p->val << eol;stampa_el(p->next) ; }

} // è tail recursivevoid stampa_el_it(lista *p){ // versione iterativa

while (p != NULL) {cout << p->val ;p = p->next ; }

}

ricerca di un elemento nella lista bool search_el(lista *p, const int e){ // versione ricorsiva

if (p == NULL) return(false) ;else if (p->val == e) return(true) ;else return(search_el(p->next, e)) ;

} // è tail recursivebool search_el_it(lista *p, const int e){ // versione iterativa

bool f = false ;while ((p != NULL) && (!f)){

if (p->val == e) f = true ;else p = p->next ; }

return(f) ;}

Page 28: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 28

tipi di dato astratto/le liste/revert

problema: scrivere una funzione una funzione iterativa che prende in input

una sequenza di caratteri che termina con il “.” e la stampa invertita.

void revert(){

char c ;lista *p , *q;p = NULL ;cin >> c ;while (c != '.') {

q = new lista ;q->val = c ;q->next = p ;p = q ;cin >> c ;

}cout << "\n la sequenza invertita e`: " ;while (p != NULL){

cout << p->val ; p = p->next ;}}

Page 29: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 29

strutture dati dinamiche/esercizi

1. implementare il tipo di dato pila con le operazioni di (a) creazione della pila vuota, (b)

push = inserimento di un elemento nella pila, (c) pop = eliminazione di un

elemento dalla pila; (d) top = valore dell’ elemento in testa alla pila

2. implementare il tipo di dato coda con le operazioni di (a) creazione della coda vuota,

(b) enqueue = inserimento di un elemento nella coda, (c) dequeue =

eliminazione di un elemento dalla coda; (d) top_el = valore dell’ elemento in testa

alla coda

3. implementare il tipo di dato insieme con le operazioni di (a) creazione dell’insieme

vuoto, (b) is_in = appartenenza di un elemento all’insieme (c) union = unione di

due insiemi; (d) intersection = intersezione di due insiemi

Page 30: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 30

liste/varianti

• alcune delle operazioni precedenti sono scomode da implementare suliste come quelle viste fin'ora

• possiamo modificare leggermente la struttura dati lista per risolvereproblemi quali– accesso all'ultimo elemento

• nelle liste semplici è necessario scorrere tutta la lista

• è sufficiente tenere in una variabile statica il puntatore all'ultimo elementodella lista

– spostamento all'indietro

• nelle liste semplici è necessario scorrere tutta la lista cercando l'elemento chepunta a quello corrente

• è sufficiente tenere in ogni elemento un puntatore al precedente

• nel primo elemento questo puntatore avrà valore NULL• queste liste si chiamano liste bidirezionali o doppiamente linkate

Page 31: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 31

lista/varianti/quando usarle

• vantaggio: semplificano alcuni tipi di operazioni– ricerca di alcuni elementi

• svantaggio: complicano altre operazioni– le informazioni addizionali devono essere aggiornate

– si complicano inserimenti e cancellazioni

• la ricerca del miglior compromesso– si cerca di rendere più efficienti le operazioni più frequenti

• esempio: se ho molti inserimenti e cancellazioni cercherò di usare lastruttura più semplice

Page 32: I PUNTATORI E LE STRUTTURE DATI DINAMICHElaneve/html/linguaggi/lez9-DINAMICHE.pdf · slide 3 prologo le strutture dati dinamiche sono strutture dati le cui dimensioni possono essere

slide 32

liste bidirezionali: esercizi

• prendere in input caratteri e creare una lista bidirezionale che li contenga. Stampare icaratteri inseriti in ordine inverso e in ordine normale

• scrivere un programma che consente all'utente di lavorare su una lista bidirezionale diinteri con le seguenti operazioni

– aggiungere un elemento in fondo

– vedere le informazioni dell'elemento corrente

– andare avanti di uno

– andare indietro di uno

– eliminare l'elemento corrente