strutture dati elementari parte 6 vettori e ricerca binaria matrici e triangolo di tartaglia records...

53
Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi http://www.di.unito.it/~stefano Corso B: Prof. Ugo de’ Liguoro http://www.di.unito.it/~deligu

Upload: carla-boni

Post on 02-May-2015

220 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Strutture dati elementari

Parte 6

Vettori e ricerca binaria

Matrici e triangolo di Tartaglia

Records (cenni)

Corso A: Prof. Stefano Berardi http://www.di.unito.it/~stefanoCorso B: Prof. Ugo de’ Liguoro http://www.di.unito.it/~deligu

Page 2: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

“Un quadrato magico di numeri”

Albert Durer. Melencolia,1514

(dettaglio)

16 3 2 13

5 10 11 8

9 6 7 12

4 15 14 1

Page 3: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Indice Parte 6: i Vettori1. Strutture dati: i vettori.2. Esempi elementari: stampa, somma,

test di uguaglianza, inversione per vettori.

3. Esempi più complessi: ricerca lineare e binaria per vettori.

4. Matrici: il triangolo di Tartaglia.5. Records e vettori parzialmente

riempiti (cenni).

Page 4: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

1. Strutture dati: I Vettori

• In generale, le strutture dati sono un modo per rappresentare insiemi di informazioni nella memoria di un computer

• Una semplice variabile è un caso banale di una struttura dati, un modo per rappresentate una singola informazione.

• In questa parte del corso studieremo strutture dati per rappresentare insiemi di dati di tipo omogeneo, i vettori e le matrici, e per rappresentare dati di tipo eterogeneo, i record.

Page 5: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Vettori (o “array”) in C++

• Un vettore v (array) è una sequenza di n oggetti tutti del medesimo tipo, detti elementi del vettore, per qualche n>0 detto la dimensione del vettore.

• Gli elementi del vettore sono indicizzati utilizzando interi positivi, da 0 fino a n-1, immaginati disposti come segue:

v[0], v[1], … , v[n-1]

Page 6: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Notazioni per i vettori

• Le notazioni che seguono NON sono codice C/C++, ma sono la notazione che usiamo quando parliamo dei vettori:

i..j = {kZ| i k j} intervallo di interiv[i..j] = {v[i], v[i+1], … , v[j]}

• Quindi, se i > j allora i..j = lista vuota; se un vettore v ha n elementi questi formano l’insieme v[0..n-1].

Page 7: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

I vettori nella memoria RAM

• Gli elementi di un vettore occupano spazi di memoria consecutivi nella memoria RAM della macchina di Von Neumann. L’indirizzo &v[i] di ogni elemento si calcola dunque con la formula: &v[i] = &v[0] + id, dove d = sizeof (tipo di v[])

v[0] ind. b

v[1] ind. b+d

v[2] ind. b+2d

b = indirizzo base = &v[0] =indirizzo v[0] (es.:byte n. 1

milione)

d = dimensione di ogni elemento (es.: 4 bytes)

v[i]indirizzo

b+i*d

&v[i] = indirizzo v[i] = b+id

i = indice di v[i] (detto anche “spiazzamento” ). Es.: i=100, indirizzo di v[i] = 1 000 400.

v

Page 8: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Vettori: dichiarazione

• Un vettore v in C++ è una costante di tipo indirizzo. Viene identificato con &v[0], l’indirizzo del suo primo elemento. La dichiarazione di v consiste nell’indicazione del nome e del tipo degli elementi del vettore, e nell’indicazione del loro numero, detto la dimensione del vettore. Con sizeof(v) si indica invece il numero di bytes occupati dal vettore: int v[100];

Tipo degli elementi Nome del vettore:

v vale &v[0]

100 = numero degli elementi, o

dimensione di v Invece: sizeof(v) =

100*sizeof(int) = 400

Page 9: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Vettori: l’errore più comune

• La dimensione di un vettore deve essere una costante o una variabile già assegnata.

• Quindi le seguenti righe sono errate (ma purtroppo il compilatore non lo segnala!):int dim; double w[dim];

/* ERRORE: la variabile dim, per il solo fatto di essere dichiarata, ha un valore, ma non si può prevedere quale. Quindi si crea un vettore di dimensione “casuale”, a volte di miliardi di elementi, producendo in quest’ultimo caso un “crash” di programma */

Page 10: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Accesso agli elementi di un vettore

• Per accedere ai singoli elementi di un vettore si usano gli indici: attenti a non confondere gli indici con la dimensione che compare nella dichiarazione.

int v[100];

/* dichiarazione */

v[0] = 6;

/* assegnazione, accesso in scrittura */

int n = v[0];

/* assegnazione, accesso in lettura */

Gli interi tra [ ] hanno diverso significato in una dichiarazione e in una assegnazione: nella dichiarazione, 100 è la dimensione, nell’assegnazione, 0 è un indice

Page 11: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Inizializzazione attraverso un ciclo

• Il programma che segue inizializza a 0 tutti gli elementi del vettore v:

int v[100];

for (int i = 0; i < 100; i++)

v[i] = 0;

i dichiarato entro il for esisterà soltanto

entro il for

Nell’esecuzione del for, i assumerà tutti i valori tra 0 e 99

Prima dell’inizializzazione, tutti gli elementi di v, avendo un indirizzo di memoria, hanno comunque un valore, ma un valore “casuale”: provate a stamparli.

Page 12: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Inizializzazione attraverso una dichiazione

• Il C++ consente di definire (quindi anche di inizializzare) un vettore elencandone gli elementi. Non è necessario indicare il numero degli elementi, che viene calcolato:

double a[] = {22.2, 44.4, 66.6};

// alloca un vettore a di 3 float con

// a[0] = 22.2, a[1] = 44.4, a[2] = 66.6

Guardate l’esempio 6.3 del testo di Hubbard: spiega che la dimensione di a si calcola con la formula

sizeof(a)/sizeof(double)

Page 13: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Attenti a non uscire dai limiti di un vettore

• Se un vettore ha dimensione d ed i<0, oppure i d, allora v[i] non dovrebbe essere definito.

• Invece, in C/C++, v[i] esiste sempre, è per definizione il contenuto dell’indirizzo di memoria calcolato dalla formula:

&v[0] + i sizeof (tipo di v[])

• ossia un valore a caso!! Questa convenzione è introdotta per semplicità di calcolo. Il compilatore non ci avvisa quando utilizziamo un v[i] con i<0, oppure i d, sta a noi evitare che accada.

Questo non accade in PASCAL: vedi Hubbard paragrafo 6.4

Page 14: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

2. Alcuni semplici esempi: stampa di un vettore

• La stampa di un vettore deve avvenire “elemento per elemento” (dunque usando ad es. un ciclo for):

int v[100];

for (int i = 0; i < 100; i++)

cout << v[i];

Se si scrive invece: cout << v; dato che v è identificato con l’indirizzo di v[0] si stampa

l’indirizzo di v[0] (in esadecimale)

Page 15: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Somma e media di un array di numeri

double v[100];

double somma = 0;

for (int i = 0;

i < 100; i++)

somma = somma + v[i];

double media = somma/100.0; /*dividiamo per un numero reale per evitare l’arrotondamento*/

Per tutte le sommatorie di cui non si conosca a priori nemmeno un termine, il valore iniziale dell’accumulatore è 0, l’elemento neutro della somma

Anche la somma di un vettore deve avvenire “elemento per elemento” (dunque usando ad es. un ciclo for):

Page 16: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Un test di uguaglianza errato

• Se applichiamo il test == a due vettori distinti otteniamo risposta costantemente uguale a false:int v[100], w[100];

if (v == w) …

/* v, w sono identificati con gli indirizzi dei loro primi elementi, dunque il test == confronta questi ultimi. Dato che v, w sono “allocati” in posizioni diverse della memoria, i loro primi elementi hanno diversi indirizzi, anche quando v, w hanno elementi di valore uguale. Dunque v==w vale sempre false. */

Page 17: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Un test di uguaglianza corretto

• Per decidere se due array di egual tipo e egual dimensione N hanno valori uguali per indici uguali, si devono confrontare tutti gli elementi usando un’iterazione. Ecco una soluzione con un WHILE:/* Il ciclo while trasporta il contatore i al primo indice per cui v[i]!=w[i], se ne esiste uno, altrimenti trasporta i fino ad N */int i = 0; while (i < N && v[i] == w[i]) i++;if (i == N) cout << "v,w hanno elementi uguali per indici uguali"; else /* i < N */ cout << "v, w hanno diverso l’elemento di posto" << i;

Page 18: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Un test di uguaglianza corretto 2

int i;

for (i=0; i < N && v[i] == w[i]; i++){ };

//il corpo del FOR e’ vuoto

if (i == N) cout << "v,w hanno uguali per indici uguali"; else cout << "v, w hanno diverso l’elemento di posto" << i;

i è dichiarata fuori del for perché l’if che segue ne possa fare uso

• Per decidere se due array di egual tipo e egual dimensione N hanno valori uguali per indici uguali, si devono confrontare tutti gli elementi usando un’iterazione. Ecco la traduzione della soluzione precedente in un ciclo FOR:

Page 19: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Passaggio di un vettore ad una funzione

• Un array viene passato alle funzioni sempre per indirizzo. Attenzione: nella dichiarazione del parametro scriviamo int a[], nella chiamata non ripetiamo il tipo e scriviamo solo a:int sum( int a[], int n) /* prec.:0<=n<=dim.a post.cond:sum(a,n) = somma di a[0..n-1]*/

{int i,s; for (i=0,s=0; i<n; i++) s=s+a[i];

return s;}

int main(){ int a[] = { 11, 33, 55, 77 };

int size = sizeof(a)/sizeof(int); //num.el. di a

cout <<"sum(a,size) ="<<sum(a,size)<<endl;}

Page 20: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Modifica di un vettore

• Poiché un vettore viene passato per riferimento (indirizzo) se una chiamata di funzione modifica gli elementi del vettore, queste modifiche sono permanenti:

void scambia (int v[], int i, int j)// pre: 0 i, j < dimensione di v// post: scambia v[i] con v[j]{ int temp = v[i]; v[i] = v[j]; v[j] = temp; }

Page 21: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Inversione di un vettore v

• Idea. Poniamo due indici i, j agli estremi di v e muoviamo i, j uno verso l’altro. Scambiamo tra loro gli elementi di posto i e j, fino a che tutti gli elementi alla sinistra di v sono scambiati con tutti gli elementi alla destra di v.void inverti (int v[], int n) /* PRE: 0 n dimensione di v. POST: elementi v[0..n-1] in ordine inverso */{for (int i = 0, int j=n-1; i<j; i++,j--) scambia(v, i, j);} Attenzione: se un vettore v è

un parametro attuale di una funzione (per es. scambia) NON si scrive int v[] ma v

v[0] v[1] … v[n-2]v[n-1]i=0 i=1 j=n-2 j=n-1

Page 22: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

3. Ricerca Lineare e Binaria

• Si vuole decidere se un intero n appartiene alla sequenza rappresentata dal vettore v. Il metodo più semplice è la ricerca lineare: confrontiamo n con v[0], v[1], v[2], … in quest’ordine.bool Member (int n, int v[], int dim)/* pre: la dimensione di v e’ >= dim >=0. post: restituiamo true esiste i tale che v[i]==n */{bool trovato = false; /* “trovato” indica se n e’ gia’ stato trovato. “trovato” puo’ cambiare solo da false a true, mai viceversa.*/for(int i=0;i<dim;i++){if(v[i]==n)trovato=true;} return trovato;}

Page 23: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca lineare con interruzione: uso di una variabile “flag”

• Per efficienza, potremmo voler interrompere la ricerca di n non appena troviamo n. A tal fine, definiamo un valore booleano “trovato” che parte da “vero”, e non appena “trovato” vale vero usciamo. Il test del ciclo quindi deve essere: continuiamo se “!trovato” è vero. Una variabile booleana che ci avvisa quando uscire da un ciclo è detta una “flag”.bool Member (int n, int v[], int dim) /* pre: la dim. di v e’ >= dim >=0. post: true sse esiste i t.c. v[i] == n*/{bool trovato = false; //detta variabile “flag” for (int i=0; i<dim && !trovato == true; i++) if (v[i] == n) trovato = true; return trovato;}

Page 24: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca lineare con interruzione: seconda soluzione

• Possiamo eliminare la “flag” trovato, spostando (la negazione di) v[i] == n nel test del for. In tal caso, dobbiamo dichiarare i fuori dal for:bool Member (int n, int v[], int dim)// pre: la dimensione di v e’ >= dim >= 0// post: true sse esiste i t.c. v[i] == n{ int i; for (i=0; i < dim && v[i] != n; i++){}; return (i < dim);}

Se i < dim è vero, il for è terminato perchè v[i] == n , altrimenti è terminato perchè il vettore è finito senza trovare n

Page 25: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria

Se un vettore (per es. di interi) è ordinato in senso crescente, la ricerca di un elemento nel vettore può essere enormemente accelerata sfruttando il metodo della Ricerca Binaria:

1. Manteniamo due indici, i e j, a delimitazione della porzione v[i…j] di v in cui cercare

2. Ad ogni passo confrontiamo n con il valore di indice medio in i..j, cioè m=(i+j)/2

3. Se v[m] != n allora cerchiamo in v[i..m-1] o in v[m+1..i] a seconda che n < v[m] oppure v[m] < n.

Daremo ora una descrizione dettagliata del funzionamento della ricerca binaria, in 5 tappe.

Page 26: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 1: pre- e post-condizioni

1. Definiamo il problema. Input: il “valore cercato” in v è n. Pre-condizione: il vettore v di dimensione dim è ordinato.

• Post-condizione: restituire l’indice del valore cercato (un i tale che v[i]=n, se esiste), altrimenti la lunghezza dim di v (dim sta per “non trovato”)

0 dim-1=193 5 6 1318212125364349515360727483889195

0 dim-1=193 5 6 1318212125364349515360727483889195

Valore cercato: n = 25. Indice del valore cercato: 7 ( v[7]=25)7

Page 27: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 2: una proprietà invariante

• 2. Individuiamo una proprietà “invariante” della ricerca binaria, cioè una proprietà significativa che resta vera durante tutta la durata della ricerca binaria:

• Propr. Invariante: durante la ricerca binaria considero solo dei segmenti v[i…j] di v tali che: se n è in v, allora n è in v[i…j].

Per es.: se n=25 è in v, allora n è in v[i..j] = v[3..16].

indice 03 5 6 1318212125364349515360727483889195

i=3 j=16 indice 19Cerco n=25 in v[i…j]

v[i…j]

Page 28: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 3: il funzionamento

• 3. La ricerca binaria cerca un modo per avvicinarsi alla soluzione mantenendo vero l’invariante

• Passo generico: dividiamo il sottovettore in due parti (quasi) uguali. Caso 1. Se n si trova nel punto intermedio: restituisco m

Se il valore cercato è n = 43 allora l’ho trovato

Punto intermedio m di i…j

0 dim-1= 193 5 6 1318212125364349515360727483889195

Spazio dove avviene la ricerca di n

Page 29: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 3: il funzionamento

Valore cercato: n = 25 Punto intermedio m di i..j0 193 5 6 1318212125364349515360727483889195

Spazio di ricerca

• Passo generico: dividiamo il sottovettore in due parti (quasi) uguali. Caso 2. Se il valore n cercato è < di quello nel punto intermedio, allora, dato che il vettore è ordinato, n si trova nella parte sinistra di v[i…j].

3. La ricerca binaria cerca un modo per avvicinarsi alla soluzione mantenendo vero l’invariante

Page 30: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 3: il funzionamento

Valore cercato: n = 60 Punto intermedio m di i..j

0 193 5 6 1318212125364349515360727483889195

Spazio di ricerca

• Passo generico: dividiamo il sottovettore in due parti (quasi) uguali. Caso 3. Se il valore cercato n è > di quello nel punto intermedio, allora n si trova nella parte destra di v[i…j] .

3. La ricerca binaria cerca un modo per avvicinarsi alla soluzione mantenendo vero l’invariante

Page 31: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 4: la fine della computazione 4. Definiamo in quale momento la

computazione si deve fermare

• Quando si sia trovato il valore nel punto intermedio di indice m, oppure ….

Valore cercato (e trovato): n = 43

Punto intermedio di indice m

0 193 5 6 1318212125364349515360727483889195

Spazio di ricerca

Page 32: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 4: la fine della computazione 4. Definiamo in quale momento la

computazione si deve fermare

• …. oppure quando il sottovettore cui limitiamo la ricerca sia ridotto al vettore vuoto (cioe’ al vettore v[i…j] con i>j)

Valore cercato (e non trovato): n=23

n=23 dovrebbe essere qui in mezzo, tra 21 e 25: ma questo intervallo è vuoto. Il valore n non viene trovato.

0 193 5 6 1318212125364349515360727483889195

Page 33: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria 5:l’inizio della computazione 5. Definiamo le condizioni iniziali per

la ricerca binaria

• All’inizio, il segmento v[i…j] di vettore in cui cercare n e’ l’intero vettore n.

0 193 5 6 1318212125364349515360727483889195

Spazio di ricerca iniziale: v[0..n-1]

Page 34: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria: i dettagli della codifica dei dati

Stabiliamo ora i dettagli della codifica del segmento di vettore V[i..j] che usiamo durante la ricerca.• Il sottovettore V[i..j], a cui limitiamo la

ricerca, è compreso tra le posizioni i e j incluse

i j

• Il punto medio m ha indice: (i + j) diviso 2

• Se i > j allora il sottovettore V[i..j] è vuoto

0 193 5 6 1318212125364349515360727483889195

Spazio di ricerca in un passo generico della computazione

m

Page 35: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria: l’implementazione

• Scriviamo ora una funzione C++ che implementa la ricerca binaria, usando pre- e post-condizioni e l’invariante come commenti. La funzione ottenuta è decisamente breve rispetto a tutta la discussione che è servita a presentarla.

Page 36: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Ricerca binaria: l’implementazione

int binsearch (int n, int v[], int dim)// pre: la dim. di v e’ >= dim e v[0..dim-1] è ordinato // post: i tale che v[i] == n se ne esiste uno, altrimenti: dim{ int i = 0, j = dim - 1, m; while (i <= j) //inv. se n in v[0..n-1] allora n in V[i..j] {m = (i+j)/2; if (v[m] == n) return m; else if (n < v[m]) j = m - 1; else /* (v[m] < n) */ i = m + 1;} return dim; // dim sta per “non trovato” }

Page 37: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

4. Matrici in C++

• Una matrice a due dimensioni viene vista come un vettore bidimensionale, o di vettori, ognuno dei quali rappresenta una riga della matrice; la dichiarazione di una matrice è simile a quella vettore, eccetto che richiede due dimensioni:

double A[10][20]; // matrice 10righe x 20colonne di double A[i][j] = 7.23; // se 0 i < 10 e 0 j < 20 allora // scrive 7.23 come valore della // i-esima riga e j-esima colonna di A

Page 38: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Passaggio di un vettore bidimensionale a funzione

• Nei parametri formali di una funzione un vettore V di dimensione 1 può figurare come

• void f(int V[], int n){…}

• senza l’indicazione della lunghezza di V dentro int V[]: la lunghezza n del vettore è a sua volta un parametro, che può cambiare da una chiamata all’altra.

• Nel caso di una matrice A di due o più dimensioni, invece, le dimensioni debbono essere costanti indicate dentro A stesso, come segue:

void g(double A [10][20] ) {…}

Page 39: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Passaggio di un vettore bidimensionale a funzione

Questo tipo di dichiarazione è molto scomoda: una funzione g che stampa una matrice A di 10x20 elementi non può essere utilizzata per stampare una matrice B di 20x20 elementi, perchè double A[10][20] e double B[20][20] sono due tipi diversi.

La seconda dimensione di A, ovvero il numero 20 delle colonne di A, è purtroppo necessaria per ricostruire l’indirizzo della variabile A[i][j] nella macchina di Von Neumann, e non è ricostruibile a partire dalla sola variabile A.

void g(double A [10][20] ) {…}

Page 40: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Un esempio di uso di matrici:il triangolo di Tartaglia

Niccolò Tartaglia1499-1557

Scriveremo ora una funzione che assegna le prime n+1 righe del triangolo diTartaglia a una matrice (n+1)x(n+1). Per definizione, ogni elemento posto ai lati del triangolo di Tartaglia vale 1, e ogni altro elemento è la somma dell’elemento posto sopra e di quello posto sopra e a destra.

Page 41: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Un esempio di uso di matrici:

il triangolo di Tartaglia 1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

1 6 15 20 15 6 1

Righe da 0 a 6 del “Triangolo” in una matrice A di 7x7. Per definizione: 1 = A[0][0] = A[1,0] = A[2][0] = … =A[i,0] = … e 1 = A[0][0] = A[1,1] = A[2][2] = … = A[i,i] = … e per 0<j<i: A[i][j] = A[i-1][j-1]+A[i-1][j].

0 1 2 3 4 5 6

0

1

2

3

4

5

6

Per es.: 6 = A[4][2] = A[3][1] + A[3][2] = 3 + 3.

Page 42: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Il triangolo di Tartaglia usando una matrice

void Tartaglia(int n)// stampa righe da 0 a n del triangolo di Tartaglia{int a[n+1][n+1]; //definisce matrice (n+1)x(n+1) for (int i = 0; i<=n; ++i) // costruzione “riga per riga” {a[i][0] = 1; // assegna 1 a tutta la colonna 0 for (int j = 1; j<i; ++j) // assegna colonne da 1 a i-1 a[i][j] = a[i-1][j-1] + a[i-1][j]; a[i][i] = 1; // assegna 1 a tutta la diagonale}// stampa righe da 0 a n del triangolo …(vedi pagina seguente per sapere come) … }

Page 43: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Stampa del triangolo di Tartaglia

void Tartaglia(int n){ // definisce righe da 0 a n

… (vedi pagina precedente per sapere come) …

// stampa righe da 0 a n for (int i = 0; i <= n; ++i) { for (int j = 0; j <= i; ++j) cout << setw(4) << a[i][j]; cout << endl;} }L’istruzione setw(4) esegue la prossima stampa con almeno 4 spazi. Richiede di includere la libreria:

#include <iomanip.h>

Page 44: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

5. I records (cenni)

Un record è una tupla di valori di tipo possibilmente diverso (è questa la differenza con i vettori) a cui accediamo attraverso etichette anziché indici:

struct <nome struttura> {<tipo1> <etichetta campo1>;

...<tipok> <etichetta campok>;}

Come concetto matematico, un record corrisponde a un prodotto cartesiano: tipo1 x … x tipon mentre un vettore corrisponde a un insieme potenza: tipon

Page 45: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

I record nella memoria

• I record nella memoria di una macchina di Von Neumann sono rappresentati con celle adiacenti, ma di diversa dimensione. E’ necessario individuare ogni cella assegnadole un nome:Nome_1

Nome_k

Possiamo rappresentare i razionali come frazioni, e le frazioni come un record di due campi: numeratore e denominatore. Si tratta solo di un esempio: i razionali non sono una struttura dati abbastanza complessa da giustificare l’uso dei records.

Page 46: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Frazioni rappresentate da un record

struct Ratio {

int num; int den;};

Poiché qui i due campi hanno lo stesso tipo avremmo potuto scrivere:int num, den;

Ratio si aggiunge ai

tipi definiti nel programma

Se r e’ un record che rappresenta una frazione, indichiamo numeratore e denominatore di r con r.num e r.den

Page 47: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Record come valori di funzioni

• Diversamente dagli array, le struct in C++ sono passate (e restituite) per valore: dunque ogni chiamata costruisce una copia del record e la assegna al parametro formale della funzione

Ratio NewRatio(int n, int d) /* Pre-cond.: d!=0Post-cond.:NewRatio(n,d) restituisce il record che rappresenta n/d */{ Ratio r; r.num = n; r.den = d; return r;}

int main() { Ratio a = NewRatio(2,3); // a=2/3 }

Page 48: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Record come valori di funzioni

• Un altro esempio, la somma di frazioni. Le strutture in C++ sono passate per valore, creando delle copie dei valori passati.

Ratio SumRatio(Ratio a, Ratio b)// post: restituisce il razionale a + b{ Ratio r; r.num = a.num * b.den + a.den * a.num; r.den = a.den * b.den; return r;}int main() { Ratio a, b; …; Ratio c = SumRatio(a,b);} // c = a + b

Page 49: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Vettori parzialmente riempiti

Di un vettore occorre ricordare la dimensione; se poi se ne usa solo una parte, come abbiamo fatto nell’esercizio sui numeri primi, bisogna sapere sin dove è “riempito”, ovvero, quale è il prossimo indirizzo libero.

prox_libero

v

Se non ci sono indirizzi liberi, il prossimo indirizzo libero per definizione è la dimensione dim del vettore v.

Page 50: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Vettori parzialmente riempiti come record

• Possiamo definire un record per rappresentare vettori parzialmente riempiti. Usiamo un record con due campi: un vettore e il primo indirizzo ancora libero del vettore (se esiste)struct Array { int v[10];

int prox_libero; };

/* prox_libero = indice del prossimo indirizzo libero */

Page 51: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Funzioni su vettori parzialmente riempiti

void Mostra(Array a) /*post: stampa la parte riempita di v, e cioé: (a.v)[0..a.prox_libera-1] */

{ for (int i = 0; i < a.prox_libero; i++)

cout << a.v[i] << " ";

cout << endl;}

Un esempio di una funzione che agisce sui vettori parzialmente riempiti: la stampa di tutti gli elementi del vettore effettivamente in uso (dunque fino alla prossima posizione libera esclusa).

Page 52: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Funzioni su vettori parzialmente riempiti

bool Aggiungi(int n, Array& a)

/* post: se a.prox_libera < 10, aggiunge n in ultima pos. e restituisce true; restituisce false altrimenti */

{if (a.prox_libero < 10)

{a.v[a.prox_libero] = n; a.prox_libero++; return true;}

else return false;}

Un altro esempio di una funzione che agisce sui vettori parzialmente riempiti: come aggiungere un elemento a quelli effettivamente in uso

Page 53: Strutture dati elementari Parte 6 Vettori e ricerca binaria Matrici e triangolo di Tartaglia Records (cenni) Corso A: Prof. Stefano Berardi stefano

Riepilogo

• Vi sono due strutture dati predefinite per rappresentare collezioni finite di valori: vettori (array) e record (struct)

• I vettori hanno dimensione fissa, elementi omogenei, e sono passati per riferimento

• Vettori a due dimensioni rappresentano una matrice.

• I record hanno un numero fisso di campi individuati da nomi, hanno tipi eventualmente diversi di valori, e sono passati per valore.