• Non ci sono risultati.

Strutture dati dati statiche statiche e e dinamiche dinamiche

N/A
N/A
Protected

Academic year: 2021

Condividi "Strutture dati dati statiche statiche e e dinamiche dinamiche"

Copied!
35
0
0

Testo completo

(1)

Politecnico Politecnico di Milano di Milano

Strutture

Strutture dati dati dinamiche dinamiche

(2)

Strutture

Strutture dati dati statiche statiche e e dinamiche dinamiche

In C le dimensioni di ogni dato sono note prima dell’esecuzione

Sarebbe utile avere contenitori la cui dimensione varia a seconda delle necessità

La soluzione in C:

Ogni variabile ha sempre una dimensione prefissata…

Ma … durante l’esecuzione di un programma è possibile

creare dinamicamente nuove variabili

(3)

I I meccanismi meccanismi di di allocazione allocazione e e cancellazione

cancellazione dinamica dinamica della della memoria memoria

Vengono offerti da due funzioni di libreria

malloc e free

#include <stdlib.h> /* necessario per usare malloc e free */

#include <stdio.h>

typedef int *tipoPtr;

void main() {

tipoPtr p;

p = malloc(sizeof(int)); /*crea una variab. anonima int */

*p = 24;

printf(“%d”, *p);

free(p); /* libera lo spazio di memoria a cui p punta */

}

Restituisce la dimensione in byte di una variabile o di elementi di un certo tipo

(4)

Modello

Modello di di esecuzione esecuzione (1) (1)

Ad ogni programma in esecuzione vengono associate due aree di memoria con caratteristiche diverse

Lo stack

Contiene le aree di memoria associate alle variabili

“normali” organizzate nei rispettivi record di attivazione

Viene gestito con politica LIFO

Lo heap (mucchio)

Contiene le aree di memoria associate alle variabili

allocate dinamicamente

(5)

Modello

Modello di di esecuzione esecuzione (2) (2)

#include <stdlib.h>

#include <stdio.h>

typedef int *tipoPtr;

void main() {

tipoPtr p;

p = malloc(sizeof(int));

*p = 24;

printf(“%d”, *p);

free(p);

}

stack heap

p

(6)

Modello

Modello di di esecuzione esecuzione (2) (2)

#include <stdlib.h>

#include <stdio.h>

typedef int *tipoPtr;

void main() {

tipoPtr p;

p = malloc(sizeof(int));

*p = 24;

printf(“%d”, *p);

free(p);

}

stack heap

p

(7)

Modello

Modello di di esecuzione esecuzione (2) (2)

#include <stdlib.h>

#include <stdio.h>

typedef int *tipoPtr;

void main() {

tipoPtr p;

p = malloc(sizeof(int));

*p = 24;

printf(“%d”, *p);

free(p);

}

stack heap

p

24

(8)

Modello

Modello di di esecuzione esecuzione (2) (2)

#include <stdlib.h>

#include <stdio.h>

typedef int *tipoPtr;

void main() {

tipoPtr p;

p = malloc(sizeof(int));

*p = 24;

printf(“%d”, *p);

free(p);

}

stack heap

p

24

(9)

Aspetti

Aspetti critici critici

Dangling pointer

p = malloc(sizeof(int));

free(p);

*p = 12;

Il valore 12 viene assegnato ad un’area di memoria non più associata alla variabile anonima creata con la malloc!

Garbage

La memoria allocata dinamicamente rimane nello heap durante tutta l’esecuzione del programma a meno che non si deallochi esplicitamente

Esempio di programma che spreca memoria

p = malloc(sizeof(int));

*p = 24;

p = malloc(sizeof(int));

*p = 10;

Vengono create due aree di memoria dello heap, ma solo la seconda sarà raggiungibile tramite p. La seconda

costituisce spazzatura (garbage)

(10)

Liste

Liste a a puntatori puntatori (1) (1)

Sono costruite collegando elementi costituiti da due parti:

Il contenuto informativo

un intero, i dati di uno studente, un numero complesso, una stringa, ….

Un puntatore all’elemento seguente

Ciascun elemento viene creato con l’allocazione dinamica della memoria

“Trovare” “topi“ “è” “difficile”

heap stack

ptr

(11)

Liste

Liste a a puntatori puntatori (2) (2)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Cancellazione

“Trovare” “topi“ “è” “difficile”

ptr prec corr

(12)

Liste

Liste a a puntatori puntatori (2) (2)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Cancellazione

“Trovare” “topi“ “è” “difficile”

ptr prec corr

(13)

Liste

Liste a a puntatori puntatori (2) (2)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Cancellazione

“Trovare” “topi“ “difficile”

ptr prec corr

(14)

Liste

Liste a a puntatori puntatori (3) (3)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Inserimento

“Trovare” “topi“ “è” “difficile”

ptr corr new

“molto”

(15)

Liste

Liste a a puntatori puntatori (3) (3)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Inserimento

“Trovare” “topi“ “è” “difficile”

ptr corr new

“molto”

(16)

Liste

Liste a a puntatori puntatori (3) (3)

Vantaggi

E` possibile aggiungere o eliminare elementi al bisogno ed in modo semplice

Inserimento

“Trovare” “topi“ “è” “difficile”

ptr corr new

“molto”

(17)

Tipi

Tipi necessari necessari per costruire per costruire la lista la lista

typedef struct { int a;

int b;

} TipoDato; /* TipoDato può avere qualsiasi struttura */

typedef struct El {

TipoDato info; /*si assume che tipoDato sia stato definito precedentemente */

struct El *next; /* puntatore all’elemento seguente */

} ElemLista;

typedef ElemLista *Lista;

typedef enum {false, true} boolean; /* usato dopo */

(18)

Operazioni

Operazioni fondamentali fondamentali per la per la gestione

gestione delle delle liste liste

/* creazione di una lista vuota */

Lista crea();

/* inserimento di un elemento nella lista */

void inserisciInTesta(Lista *l, TipoDato dato);

void inserisciInCoda(Lista *l, TipoDato dato);

void inserisciInOrdine(Lista *l, TipoDato dato);

/* controllo lista vuota */

boolean listaVuota(Lista l);

/* controllo esistenza di un elemento nella lista */

boolean esiste(Lista l, TipoDato dato);

(19)

Operazioni

Operazioni fondamentali fondamentali per la per la gestione

gestione delle delle liste liste

/* cancellazione di un elemento dalla lista */

void cancella(Lista *l, TipoDato dato);

/* restituisce la sottolista costituita da tutti gli elementi di quella di partenza ad esclusione del primo */

Lista coda(Lista l);

/* stampa sullo schermo il contenuto della lista */

void stampaLista(Lista l);

(20)

Operazioni

Operazioni di di servizio servizio relative a relative a TipoDato

TipoDato

TipoDato acquisisci() {

TipoDato x;

scanf(“%d%d”, &(x.a), &(x.b));

return x;

}

boolean uguale(TipoDato d1, TipoDato d2) {

if((d1.a == d2.a)&&(d1.b == d2.b)) return true;

else return false;

}

void stampa(TipoDato d)

{ printf(“%d, %d\n”, d.a, d.b); }

(21)

Un main

Un main di di esempio esempio

void main() {

int i;

Lista lista, lista1;

TipoDato d;

lista = crea();

for(i=0;i<5;i++) {

d = acquisisci();

inserisciInTesta(&lista, d);

stampaLista(lista);

}

d = acquisisci();

if(esiste(lista, d) == vero) cancella(&lista, d);

stampaLista(lista);

lista1 = coda(lista);

stampaLista(lista1);

}

(22)

Implementazione

Implementazione di di crea crea ed ed esiste esiste

Lista crea() { return NULL; }

boolean esiste(Lista l, TipoDato dato) {

while((l!=NULL) && uguale(l->info,dato)==false) l = l->next;

if(l!=NULL) return true;

else return false;

}

l dato

info lista1

d lista

i

Attivazione main

Attivazione esiste 1

2 1 2

1 2 7 9

2 4 3 0

(23)

Implementazione

Implementazione di di crea crea ed ed esiste esiste

Lista crea() { return NULL; }

boolean esiste(Lista l, TipoDato dato) {

while((l!=NULL) && uguale(l->info,dato)==false) l = l->next;

if(l!=NULL) return true;

else return false;

}

l dato

info lista1

d lista

i

Attivazione main

Attivazione esiste 1

2 1 2

1 2 7 9

2 4 3 0

(24)

Implementazione

Implementazione di di crea crea ed ed esiste esiste

Lista crea() { return NULL; }

boolean esiste(Lista l, TipoDato dato) {

while((l!=NULL) && uguale(l->info,dato)==false) l = l->next;

if(l!=NULL) return true;

else return false;

}

l dato

info lista1

d lista

i

Attivazione main

Attivazione esiste 1

2 1 2

1 2 7 9

2 4 3 0

(25)

Implementazione

Implementazione di di inserisciInTesta inserisciInTesta

void inserisciInTesta(Lista *l, TipoDato dato) {

Lista temp;

temp = malloc (sizeof(ElemLista));

temp->info = dato;

temp->next = *l;

*l = temp;

}

l dato

info d

lista

6 7 6

7 3 0 2 4 1 2 7 9

temp

(26)

Implementazione

Implementazione di di inserisciInTesta inserisciInTesta

void inserisciInTesta(Lista *l, TipoDato dato) {

Lista temp;

temp = malloc (sizeof(ElemLista));

temp->info = dato;

temp->next = *l;

*l = temp;

}

l dato

info d

lista

6 7 6

7 3 0 2 4 1 2 7 9

temp 6 7

(27)

Implementazione

Implementazione di di inserisciInTesta inserisciInTesta

void inserisciInTesta(Lista *l, TipoDato dato) {

Lista temp;

temp = malloc (sizeof(ElemLista));

temp->info = dato;

temp->next = *l;

*l = temp;

}

l dato

info d

lista

6 7 6

7 3 0 2 4 1 2 7 9

temp 6 7

(28)

Implementazione

Implementazione di di inserisciInTesta inserisciInTesta

void inserisciInTesta(Lista *l, TipoDato dato) {

Lista temp;

temp = malloc (sizeof(ElemLista));

temp->info = dato;

temp->next = *l;

*l = temp;

}

l dato

info d

lista

6 7 6

7 3 0 2 4 1 2 7 9

temp 6 7

(29)

Implementazione

Implementazione di di cancella cancella

void cancella(Lista *l, TipoDato dato) {

Lista temp, prec;

temp = *l;

prec = NULL;

while(temp!=NULL&&

uguale(temp->info, dato)==false) { prec = temp;

temp = temp->next;

}

if (temp!=NULL && prec!=NULL) {

prec->next = temp->next;

free(temp);

}

else if(prec == NULL) {

*l=temp->next;

free(temp);

}}

l dato

d lista

1 2 1 2

temp prec

1 2 7 9

2 4 3 0

(30)

Implementazione

Implementazione di di cancella cancella

void cancella(Lista *l, TipoDato dato) {

Lista temp, prec;

temp = *l;

prec = NULL;

while(temp!=NULL&&

uguale(temp->info, dato)==false) { prec = temp;

temp = temp->next;

}

if (temp!=NULL && prec!=NULL) {

prec->next = temp->next;

free(temp);

}

else if(prec == NULL) {

*l=temp->next;

free(temp);

}}

l dato

d lista

1 2 1 2

temp prec

1 2 7 9

2 4 3 0

(31)

Implementazione

Implementazione di di cancella cancella

void cancella(Lista *l, TipoDato dato) {

Lista temp, prec;

temp = *l;

prec = NULL;

while(temp!=NULL&&

uguale(temp->info, dato)==false) { prec = temp;

temp = temp->next;

}

if (temp!=NULL && prec!=NULL) {

prec->next = temp->next;

free(temp);

}

else if(prec == NULL) {

*l=temp->next;

free(temp);

}}

l dato

d lista

1 2 1 2

temp prec

1 2 7 9

2 4 3 0

(32)

Implementazione

Implementazione di di cancella cancella

void cancella(Lista *l, TipoDato dato) {

Lista temp, prec;

temp = *l;

prec = NULL;

while(temp!=NULL&&

uguale(temp->info, dato)==false) { prec = temp;

temp = temp->next;

}

if (temp!=NULL && prec!=NULL) {

prec->next = temp->next;

free(temp);

}

else if(prec == NULL) {

*l=temp->next;

free(temp);

}}

l dato

d lista

1 2 1 2

temp prec

1 2 7 9

2 4 3 0

(33)

Implementazione

Implementazione di di cancella cancella

void cancella(Lista *l, TipoDato dato) {

Lista temp, prec;

temp = *l;

prec = NULL;

while(temp!=NULL&&

uguale(temp->info, dato)==false) { prec = temp;

temp = temp->next;

}

if (temp!=NULL && prec!=NULL) {

prec->next = temp->next;

free(temp);

}

else if(prec == NULL) {

*l=temp->next;

free(temp);

}}

l dato

d lista

1 2 1 2

temp prec

7 9 2 4 3 0

(34)

Cancella

Cancella ricorsiva ricorsiva (1) (1)

Algoritmo

Se la lista è vuota non è necessario svolgere alcuna operazione

Se il primo elemento della lista è quello cercato, lo si elimina ( *l=temp->next; free(temp);)

Altrimenti si richiama la cancella sulla sottolista che

segue il primo elemento

(35)

Cancella

Cancella ricorsiva ricorsiva (2) (2)

void cancRic(Lista *l, TipoDato dato) {

Lista temp;

temp = *l;

if(temp!=NULL)

if(uguale(temp->info, dato)==true) {

*l=temp->next;

free(temp);

}

else cancRic(&(temp->next), dato);

}

Riferimenti

Documenti correlati

sizeof(&lt;tipo di dato T&gt;) Restituisce la quantità di memoria richiesta (in char o byte) per memorizzare valori di tipo T Es., sizeof(int);. Uso della funzione sizeof()

(2010 – presentata al recente simposio internazionale CPT’10, la correlazione originale, derivata da un’analisi di regressione multipla fra dati CPTU, velocità delle onde

Questa frattura costituisce un potenziale elemento di pericolosità per la stabilità della rupe, in quanto intercetta il sistema di fratturazione prevalente (Nord-Sud) con un

Come la pila, una coda può essere implementata in modo dinamico con una lista con- catenata, effettuando però gli inserimenti alla fine della lista (ma sempre prelevandoli

Nonostante la comparazione dell’efficacia delle performance cognitive del computer-based testing (CBT) rispetto al paper-based testing (PBT) non sia ancora del tutto risolta,

 ogni elemento della lista (nodo) contiene un riferimento all’elemento seguente3.  esiste una variabile che contiene il riferimento al

 variabile d’istanza di tipo ClassName per mantenere un riferimento al nodo successivo.. 

Come evidenziato dalla definizione induttiva di sequenza, per costruire una qualsiasi lista, ` e sufficiente la costante lista vuota h i (rappresentata in C semplicemente dal