1 / 53

Strutture dati elementari

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. Albert Durer. Melencolia,1514 (dettaglio).

knox-howard
Download Presentation

Strutture dati elementari

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Albert Durer. Melencolia,1514 (dettaglio) “Un quadrato magico di numeri”

  3. Indice Parte 6: i Vettori Strutture dati: i vettori. Esempi elementari: stampa, somma, test di uguaglianza, inversione per vettori. Esempi più complessi: ricerca lineare e binaria per vettori. Matrici: il triangolo di Tartaglia. Records e vettori parzialmente riempiti (cenni).

  4. 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.

  5. 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]

  6. 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 = {kZ| i  k  j} intervallo di interi v[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].

  7. v[i] indirizzo b+i*d I vettori nella memoria RAM • Glielementidi un vettoreoccupanospazidimemoriaconsecutivinellamemoria RAM dellamacchinadi Von Neumann. L’indirizzo &v[i] diognielementosicalcoladunque con la formula: &v[i] = &v[0] + i×d,doved = sizeof (tipodi v[]) d = dimensione di ogni elemento (es.: 4 bytes) &v[i] = indirizzo v[i] = b+i×d 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) i = indice di v[i] (detto anche “spiazzamento” ). Es.: i=100, indirizzo di v[i] = 1 000 400.

  8. Nome del vettore: v vale &v[0] 100 = numero degli elementi, o dimensione di v Invece: sizeof(v) = 100*sizeof(int) = 400 Vettori: dichiarazione Tipo degli elementi • 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: intv[100];

  9. 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 fattodiesseredichiarata, ha un valore, ma non sipuòprevederequale. Quindisicrea un vettoredidimensione “casuale”, a volte dimiliardidielementi, producendo in quest’ultimocaso un “crash”diprogramma */

  10. 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. Gli interi tra [ ] hanno diverso significato in una dichiarazionee in una assegnazione: nella dichiarazione,100 è la dimensione, nell’assegnazione, 0 è un indice int v[100]; /* dichiarazione */ v[0] = 6; /* assegnazione, accesso in scrittura */ int n = v[0]; /* assegnazione, accesso in lettura */

  11. idichiaratoentroilforesisteràsoltantoentroilfor Nell’esecuzione del for, i assumerà tutti i valori tra 0 e 99 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; Prima dell’inizializzazione, tutti gli elementi di v, avendo un indirizzo di memoria, hanno comunque un valore, ma un valore “casuale”: provate a stamparli.

  12. Inizializzazione attraverso una dichiazione Guardate l’esempio 6.3 del testo di Hubbard: spiega che la dimensione di a si calcola con la formula sizeof(a)/sizeof(double) • 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

  13. Questo non accade in PASCAL: vedi Hubbard paragrafo 6.4 Attenti a non uscire dai limiti di un vettore • Se un vettore ha dimensione d edi<0, oppurei d, allorav[i] non dovrebbeesseredefinito. • Invece, in C/C++, v[i] esistesempre, è per definizioneilcontenutodell’indirizzodimemoriacalcolatodalla formula: &v[0] + i×sizeof (tipodi v[]) • ossia un valore a caso!! Questa convenzione è introdotta per semplicitàdicalcolo. Il compilatore non ciavvisaquandoutilizziamo un v[i] con i<0, oppurei d, sta a noievitarecheaccada.

  14. 2. Alcuni semplici esempi: stampa di un vettore 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) • 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];

  15. Somma e media di un array di numeri Per tutte le sommatoriedi cui non siconosca a priori nemmeno un termine, ilvaloreinizialedell’accumulatore è 0, l’elementoneutrodellasomma Anche la sommadi un vettoredeveavvenire“elemento per elemento” (dunqueusando ad es. un ciclo for): double v[100]; doublesomma = 0; for (inti = 0; i < 100; i++) somma = somma + v[i]; double media = somma/100.0; /*dividiamo per un numeroreale per evitarel’arrotondamento*/

  16. 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 sonoidentificati con gliindirizzideiloroprimielementi, dunqueil test == confrontaquestiultimi. Datoche v, w sono “allocati” in posizioni diverse dellamemoria, iloroprimielementihannodiversiindirizzi, anchequando v, w hannoelementidivaloreuguale. Dunque v==w vale sempre false. */

  17. 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 trasportailcontatorei al primo indice per cui v[i]!=w[i], se ne esisteuno, altrimentitrasportaifino ad N */ inti = 0; while (i < N && v[i] == w[i]) i++; if (i == N)cout << "v,whannoelementiuguali per indiciuguali"; else/* i < N */ cout << "v, w hannodiversol’elementodiposto" << i;

  18. i è dichiarata fuori del for perché l’if che segue ne possa fare uso Un test di uguaglianza corretto 2 • Per decidere se due array diegualtipo e egualdimensione N hannovaloriuguali per indiciuguali, sidevonoconfrontaretuttiglielementiusandoun’iterazione. Ecco la traduzionedellasoluzioneprecedente in un ciclo FOR: inti; for (i=0; i < N && v[i] == w[i]; i++){ }; //ilcorpo del FOR e’ vuoto if (i == N)cout << "v,whannouguali per indiciuguali"; elsecout << "v, w hannodiversol’elementodiposto" << i;

  19. Passaggio di un vettore ad una funzione • Un array vienepassatoallefunzionisempre per indirizzo.Attenzione: nelladichiarazione del parametroscriviamoint a[],nellachiamata non ripetiamoiltipo e scriviamo solo a: int sum( int a[],int n) /* prec.:0<=n<=dim.apost.cond:sum(a,n) = sommadi a[0..n-1]*/ {inti,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;}

  20. 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: voidscambia (int v[], inti, int j) // pre: 0  i, j < dimensionedi v // post: scambia v[i] con v[j] { int temp = v[i]; v[i] = v[j]; v[j] = temp; }

  21. v[n-2] v[n-1] v[0] v[1] … Inversione di un vettore v Attenzione: se un vettore v è un parametroattualediunafunzione (per es. scambia) NONsiscriveint v[]ma 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. voidinverti (int v[], int n) /* PRE: 0  n dimensionedi v. POST: elementi v[0..n-1] in ordineinverso */ {for (inti = 0, int j=n-1; i<j; i++,j--) scambia(v, i, j);} i=0 i=1 j=n-2 j=n-1

  22. 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 dimensionedi v e’ >= dim >=0. post: restituiamo true esistei tale che v[i]==n */ {booltrovato = false; /* “trovato” indica se n e’ gia’ statotrovato. “trovato” puo’ cambiare solo da false a true, mai viceversa.*/ for(inti=0;i<dim;i++){if(v[i]==n)trovato=true;} returntrovato;}

  23. 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 sseesisteit.c. v[i] == n*/ {booltrovato = false;//dettavariabile “flag” for (inti=0; i<dim && !trovato == true; i++) if (v[i] == n) trovato = true; returntrovato;}

  24. Ricerca lineare con interruzione: seconda soluzione Se i < dim è vero, il for è terminato perchè v[i] == n , altrimenti è terminato perchè il vettore è finito senza trovare n • 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 dimensionedi v e’ >= dim >= 0 // post: true sseesisteit.c. v[i] == n { inti; for (i=0; i < dim && v[i] != n; i++){}; return (i < dim);}

  25. 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: • Manteniamo due indici, i e j, a delimitazione della porzione v[i…j] di v in cui cercare • Ad ogni passo confrontiamo n con il valore di indice medio in i..j, cioè m=(i+j)/2 • 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.

  26. 95 53 95 91 88 18 60 74 21 25 36 43 49 51 60 21 72 13 51 83 53 91 83 74 72 13 88 21 21 25 36 43 49 18 3 3 5 6 5 6 Ricerca binaria 1: pre- e post-condizioni 7 1. Definiamoilproblema. Input: il “valorecercato” in v è n.Pre-condizione:ilvettore v didimensione dim è ordinato. • Post-condizione:restituirel’indice del valorecercato (un i tale che v[i]=n, se esiste), altrimenti la lunghezza dim di v (dimsta per “non trovato”) 0 dim-1=19 0 dim-1=19 Valorecercato: n = 25. Indice del valorecercato:7 (v[7]=25)

  27. 43 72 60 91 88 83 13 18 95 21 25 36 74 49 21 51 53 5 3 6 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]. v[i…j] indice 0 indice 19 i=3 Cerco n=25 in v[i…j] j=16 Per es.: sen=25 è in v, allora n èin v[i..j] = v[3..16].

  28. 21 51 91 88 74 72 60 53 83 18 21 95 25 36 43 49 13 6 3 5 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 Spazio dove avviene la ricerca di n 0 dim-1= 19 Se ilvalorecercato è n = 43alloral’hotrovato Punto intermedio m di i…j

  29. 36 72 60 95 88 83 13 18 91 21 25 74 43 49 51 53 21 3 5 6 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 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]. Spazio di ricerca 0 19 Punto intermedio m di i..j Valorecercato: n = 25

  30. 36 72 60 95 88 83 13 18 91 21 25 74 43 49 51 53 21 3 5 6 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 3.Se il valore cercato n è > di quello nel punto intermedio, allora n si trova nella parte destra di v[i…j] . Spazio di ricerca 0 19 Punto intermedio m di i..j Valorecercato: n = 60

  31. 21 51 91 88 74 72 60 53 83 18 21 95 25 36 43 49 13 6 3 5 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 …. Spazio di ricerca 0 19 Valorecercato (e trovato): n = 43 Punto intermedio di indice m

  32. 21 21 13 18 91 25 36 43 95 51 53 60 72 74 83 88 49 3 6 5 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) 0 19 n=23 dovrebbeessere qui in mezzo, tra 21 e 25: ma questointervallo è vuoto. Il valore n non vienetrovato. Valorecercato (e nontrovato): n=23

  33. 25 72 60 91 88 74 13 18 83 21 95 36 43 49 51 53 21 3 6 5 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. Spazio di ricerca iniziale: v[0..n-1] 0 19

  34. 21 95 91 83 74 72 60 51 88 13 18 21 53 25 49 36 43 3 5 6 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 sottovettoreV[i..j], a cui limitiamo la ricerca, è compresotra le posizionii e jincluse Spazio di ricerca in un passo generico della computazione m 0 i j 19 • Il puntomedio m ha indice: (i + j) diviso 2 • Se i > jallorailsottovettoreV[i..j] è vuoto

  35. 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.

  36. Ricerca binaria: l’implementazione intbinsearch (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 esisteuno, altrimenti: dim { inti = 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”}

  37. 4. Matrici in C++ • Unamatrice a due dimensioniviene vista come un vettorebidimensionale, o divettori, ognunodeiqualirappresentaunarigadellamatrice; la dichiarazionediunamatrice è simile a quellavettore, eccettocherichiede 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 valoredella // i-esimariga e j-esima colonna di A

  38. Passaggio di un vettore bidimensionale a funzione • Neiparametriformalidiunafunzione un vettore V didimensione 1 puòfigurare come • void f(intV[], intn){…} • senzal’indicazionedellalunghezzadi V dentroint V[]: la lunghezzan del vettore è a suavolta un parametro, chepuòcambiaredaunachiamataall’altra. • Nelcasodiunamatrice A di due o piùdimensioni, invece, le dimensionidebbonoesserecostanti indicate dentro A stesso, come segue: void g(double A [10][20] ) {…}

  39. Passaggio di un vettore bidimensionale a funzione void g(double A [10][20] ) {…} Questotipodidichiarazione è molto scomoda: unafunzione g chestampaunamatrice A di 10x20 elementi non puòessereutilizzata per stampareunamatrice B di 20x20 elementi, perchèdouble A[10][20] e double B[20][20] sono due tipi diversi. La secondadimensionedi A, ovveroilnumero 20 dellecolonnedi A, è purtropponecessaria per ricostruirel’indirizzodellavariabile A[i][j] nellamacchinadi Von Neumann, e non è ricostruibile a partiredalla sola variabile A.

  40. Un esempio di uso di matrici:il triangolo di Tartaglia Scriveremooraunafunzionecheassegna le prime n+1 righe del triangolodiTartaglia a unamatrice (n+1)x(n+1). Per definizione, ognielementopostoailati del triangolodiTartaglia vale 1, e ognialtroelementoè la sommadell’elementopostosopra e diquellopostosopra e a destra. Niccolò Tartaglia 1499-1557

  41. Un esempio di uso di matrici:il triangolo di Tartaglia 0 1 2 3 4 5 6 Righeda 0 a 6 del “Triangolo” in unamatrice 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]. 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 0 1 2 3 4 5 6 Per es.: 6 = A[4][2] = A[3][1] + A[3][2] = 3 + 3.

  42. Il triangolo di Tartaglia usando una matrice voidTartaglia(int n) // stamparigheda 0 a n del triangolodiTartaglia {int a[n+1][n+1]; //definiscematrice (n+1)x(n+1) for (inti = 0; i<=n; ++i) // costruzione “riga per riga” {a[i][0] = 1; // assegna 1 a tutta la colonna 0 for (intj = 1; j<i; ++j) // assegnacolonneda 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} // stamparigheda 0 a n del triangolo …(vedipaginaseguente per sapere come) … }

  43. Stampa del triangolo di Tartaglia voidTartaglia(int n) { // definiscerigheda 0 a n … (vedipaginaprecedente per sapere come) … // stamparigheda 0 a n for (inti = 0; i <= n; ++i) { for (int j = 0; j <= i; ++j) cout << setw(4) << a[i][j]; cout << endl;} } L’istruzionesetw(4) esegue la prossimastampa con almeno 4 spazi. Richiedediincludere la libreria: #include <iomanip.h>

  44. 5. I records (cenni) Un record è unatupladivaloriditipopossibilmentediverso (è questa la differenza con ivettori) a cui accediamoattraversoetichetteanziché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

  45. 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 Possiamorappresentareirazionali come frazioni, e le frazioni come un record di due campi: numeratore e denominatore. Si tratta solo di un esempio: irazionali non sonounastrutturadatiabbastanzacomplessadagiustificarel’usodei records.

  46. Poiché qui i due campi hanno lo stesso tipo avremmo potuto scrivere: int num, den; Frazioni rappresentate da un record Ratio si aggiunge ai tipi definiti nel programma struct Ratio { int num; int den;}; Se r e’ un record cherappresentaunafrazione, indichiamonumeratore e denominatoredi r con r.num e r.den

  47. 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!=0 Post-cond.:NewRatio(n,d) restituisceil record cherappresenta n/d */ { Ratio r; r.num = n; r.den = d; return r;} int main() { Ratio a = NewRatio(2,3); // a=2/3 }

  48. 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: restituisceilrazionale 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

  49. 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. v prox_libero Se non cisonoindirizziliberi, ilprossimoindirizzolibero per definizioneè la dimensione dim del vettore v.

  50. 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 { intv[10]; intprox_libero; }; /* prox_libero = indice del prossimoindirizzolibero */

More Related