2000 Prentice Hall, Inc. All rights reserved. Capitolo 6 (Deitel) I vettori Sommario Introduzione Vettori Dichiarazione di vettori Inizializzazione di vettori Esempio di uso dei vettori Vettori di caratteri Passare i vettori alle funzioni Ordinare i vettori Caso di studio: calcolare media, mediana e moda usando i vettori Ricerca nei vettori: ricerca lineare e ricerca binaria Vettori multidimensionali
2000 Prentice Hall, Inc. All rights reserved Introduzione Supponiamo di dover rappresentare N dati dello stesso tipo –La temperatura di ogni giorno di questo mese, o laltezza degli studenti di questa classe, o il valore di un titolo in borsa ad ogni ora di oggi, ecc.. –Ognuno dei casi precedenti comprende un gran numero di dati omogenei –Con le conoscenze attuali, li rappresenteremmo con N variabili dello stesso tipo, ma è davvero la scelta migliore? –Fortunatamente il C offre una soluzione più adatta a questa situazione Vettori (o array) –Costituiscono il primo tipo di dato strutturato che vedremo nel corso –Sono strutture dati statiche contenenti una serie di dati omogenei, ovvero che hanno una caratteristica che li accomuna: il tipo –Esempi: una serie di numeri, una serie di caratteri, ecc.. –Con il termine statiche si intende che hanno dimensione (numero di elementi) prefissata e mai variabile durante lesecuzione del programma –In C esistono anche strutture dati dinamiche, cioè la cui dimensione può variare nel corso del programma Verranno affrontate nei capitoli successivi
2000 Prentice Hall, Inc. All rights reserved Vettori (1/2) Vettore –E una collezione di elementi dello stesso tipo Tale tipo individua il tipo del vettore –E ununica variabile, per cui tutti suoi elementi condividono un nome comune Tale nome individua il nome del vettore –I valori dei vari elementi del vettore vengono memorizzati in locazioni di memoria contigue E una sequenza indicizzata di elementi –La cui dimensione è fissata e nota a priori –Per accedere ad un elemento, si deve specificare il nome del vettore e il numero la sua posizione Sintassi: nome_vettore[indice] –Nellesempio, contiene N elementi di nome c : c[0], c[1]... c[n-1] –Il primo elemento ha indice/posizione 0 –Li-esimo elemento ha indice/posizione i-1 –Lultimo elemento ha indice/posizione n-1 c[6] Nome del vettore (si noti che tutti gli elementi di questo vettore hanno lo stesso nome, c) c[0] c[1] c[2] c[3] c[11] c[10] c[9] c[8] c[7] c[5] c[4] Numero della posizione di ogni elemento allinterno del vettore c (indice)
2000 Prentice Hall, Inc. All rights reserved Vettori (2/2) Ogni elemento di un vettore va trattato come una qualsiasi variabile dello stesso tipo –Sia per le operazioni di assegnamento di valori allelemento, sia per le operazioni che usano lelemento per effettuare calcoli o stampa a video c[0] = 3; printf( "%d", c[0] ); printf( "%d", c[0] + c[1] + c[2] ); x = c[2] / 2; –Nellaccesso ad un elemento, lindice può essere dato da una variabile precedentemente assegnata o perfino da unespressione In tal si prende lelemento in posizione pari al valore corrente della variabile o al risultato dellespressione Se x=3, allora c[5-2] == c[3] == c[x] Se a=5 e b=6, allora c[a+b]++ incrementa il 12° elemento del vettore c
2000 Prentice Hall, Inc. All rights reserved Dichiarazione di vettori Un vettore viene dichiarato specificando: –Il nome dellarray, condiviso da tutti i suoi elementi –Il tipo del vettore, condiviso da tutti i suoi elementi –Il numero degli elementi contenuti (dimensione dellarray) Tipo_vettore Nome_vettore[Numero_elementi]; –Esempi: int c[ 10 ]; float MyArray[ 3284 ]; Si noti che il C obbliga a specificare esplicitamente la dimensione (statica) del vettore in fase di dichiarazione –Non farlo comporta la generazione di un errore in compilazione –La dimensione è data da un numero o da una costante (#define..) Per dichiarare insieme più vettori dello stesso tipo –Si usa la stessa sintassi valida per ogni altra variabile semplice int b[ 100 ], x[ 27 ];
2000 Prentice Hall, Inc. All rights reserved Inizializzazione di vettori In fase di dichiarazione, un vettore può essere inizializzato –I suoi valori iniziali vanno specificati tra { } e separati da virgole int n[5] = {1, 2, 3, 4, 5 }; –Se non ci sono abbastanza inizializzatori rispetto alla dimensione indicata esplicitamente, gli elementi più a destra sono inizializzati a 0 –Se invece ce ne sono troppi, si genera un errore di sintassi Solo quando si unisce dichiarazione e inizializzazione –Si può omettere la dimensione del vettore, in quanto automaticamente determinata in base al numero di inizializzatori –Nel caso di int n[] = { 1, 2, 3, 4, 5 }; ho 5 inizializzatori, perciò la dimensione del vettore viene fissata a 5 elementi Il C non ha meccanismi di controllo sui limiti dei vettori –Dato un vettore di dimensione N, quando si accede ad una posizione superiore a (N-1) si ha un errore logico, non rilevato dal compilatore –Farlo può portare ad errori di indirizzamento (memory fault) o sporcare altre variabili in memoria, rendendo così lerrore difficile da localizzare –E compito del programmatore fare in modo di non eccedere tali limiti
2000 Prentice Hall, Inc. All rights reserved Esempio di uso dei vettori 1/* Fig. 6.8: fig06_08.c - Visualizzazione di istogrammi */ 2#include 3#define SIZE 7 4 5int main(){ 6 int n[ SIZE ] = { 19, 3, 15, 7, 11, 9, 13 }; 7 int i, j; 8 9 printf( "%s%13s%17s\n", "Elemento", "Valore", Istogramma" ); 10 for ( i = 0; i <= SIZE - 1; i++ ) { 11 printf( "%8d%13d ", i, n[ i ]) ; 12 for ( j = 1; j <= n[ i ]; j++ ) printf( "%c", '*' ); 13 printf( "\n" ); 14 } 15 return 0; 16} Elemento Valore Istogramma 0 19 ******************* 1 3 *** 2 15 *************** 3 7 ******* 4 11 *********** 5 9 ********* 6 13 ************* 1. Inizializza il vettore 2. Ciclo per la stampa di righe/colonne Visualizzazione del programma
2000 Prentice Hall, Inc. All rights reserved Vettori di caratteri (1/4) Vettori di caratteri (stringhe) –La stringa first" può essere implementata come vettore di caratteri In tal caso ogni stringa di N lettere si traduce in un vettore di (N+1) caratteri N+1 perchè il C obbliga a terminare ogni stringa con il carattere nullo \0, che occuperà quindi lultima cella del vettore –Ogni vettore di caratteri può essere inizializzato con una stringa posta tra doppi apici o dalla sequenza di caratteri tra { }, a patto che lultimo sia \0 char string1[] = first"; char string1[] = { 'f', 'i', 'r', 's', 't', '\0' }; Il vettore string1 ha quindi effettivamente 6 elementi Nel primo caso, il carattere nullo è aggiunto a fine vettore automaticamente Lo stesso avviene se il vettore è inizializzato da una scanf con formato %s –Lunico modo per inizializzarlo con la sequenza di caratteri omettendo il carattere nullo in coda è dare la dimensione del vettore esplicitamente char string1[6] = { 'f', 'i', 'r', 's', 't' }; Anche in questo caso il carattere nullo è aggiunto in coda automaticamente Per evitare errori, si dà una dimensione maggiore del numero di caratteri
2000 Prentice Hall, Inc. All rights reserved Vettori di caratteri (2/4) Si può usare un vettore di N caratteri per memorizzare anche stringhe più corte di N-1 caratteri –Così facendo le celle dopo quella contenente il carattere nullo sono concettualmente vuote e di fatto contengono valori casuali (senza senso) –Mettere il carattere nullo permette di individuare la parte utile della stringa Acquisizione di una stringa in input scanf( "%s", string2 ) ; –Il nome del vettore rappresenta l' indirizzo in memoria del vettore, per cui la & non è necessaria nell scanf –Vengono acquisiti tutti i caratteri finchè si incontra il primo spazio bianco Tutto quello che scrivo dopo lo spazio viene inesorabilmente perso Per acquisire frasi, servono altri metodi (es. più scanf in sequenza) –Non essendoci controllo sui limiti, si deve fare attenzione anche qui Non scrivere oltre la fine dichiarata del vettore (causa errori logici) –Se invece la stringa è acquisita con un ciclo carattere per carattere Attenzione che quando si preme invio, anchesso è acquisito come carattere \n
2000 Prentice Hall, Inc. All rights reserved Vettori di caratteri (3/4) Stampa della stringa –La si può stampare con ununica printf con formato %s printf(%s,string1) che stampa tutti i caratteri fino a quello nullo –Oppure la si stampa carattere per carattere, con un ciclo a sentinella avente flag pari ovviamente al carattere nullo Ad esempio printf (%c,string1[3]) stamperà il carattere 's' Gli errori logici più comuni (non rilevati dal compilatore): –Inizializzare la stringa omettendo sia la dimensione del vettore che il carattere nullo di chiusura Se la stampo con %s, ottengo una stringa diversa da quella desiderata Se la stampo con il ciclo controllato da sentinella vado in loop infinito –Inizializzare la stringa omettendo il carattere nullo di chiusura e mettendo una dimensione pari al numero di inizializzatori (escluso il carattere nullo) Se la stampo con %s, ottengo una stringa diversa da quella voluta Se la stampo con il ciclo a sentinella vado in loop infinito –Stampare i caratteri con indice che è oltre la dimensione del vettore Stampa caratteri casuali senza senso, anche se era stato messo il carattere nullo
2000 Prentice Hall, Inc. All rights reserved Vettori di caratteri (4/4) 1/* Fig. 6.10: fig06_10.c 2 Trattare un vettore di caratteri come una stringa */ 3#include 4 5int main(){ 6 char stringa1[ 20 ], stringa2[] = "stringa letterale"; 7 int i; 8 9 printf(" Inserire una stringa: "); 10 scanf( "%s", stringa1 ); 11 printf( La prima stringa è: %s\nLa seconda stringa è: %s\n 12 La prima con gli spazi è:\n", stringa1, stringa2 ); 13 for ( i = 0; stringa1[ i ] != '\0'; i++ ) 14 printf( "%c ", stringa1[ i ] ); 15 printf( "\n" ); 16 return 0; 17} Inserire una stringa: Ciao a tutti La prima stringa è: Ciao La seconda stringa è: stringa letterale La prima con gli spazi è: C i a o 1. Inizializza i vettori di caratteri 2. Acquisisce la stringa 3. Stampa i vettori come stringhe, direttamente 4. Ciclo per la stampa carattere per carattere inserendo degli spazi tra ogni carattere Visualizzazione del programma
2000 Prentice Hall, Inc. All rights reserved Passare i vettori alle funzioni (1/4) Passare i vettori come parametri di funzioni –In C, il metodo di default di passaggio dei parametri è per valore Dentro la funzione si usa/modifica una copia locale della variabile passata –I vettori fanno eccezione, sono passati automaticamente per riferimento Si passa il loro vero indirizzo e non una copia del loro contenuto Modifiche del vettore nella funzione si riflettono anche allesterno perché vanno a modificare le locazioni di memoria originali dellarray –Il nome del vettore rappresenta lindirizzo in memoria del primo elemento Quindi la funzione sa sempre dove il vettore è memorizzato Essendo ogni vettore costituito da celle contigue, basta conoscere la posizione della prima perché siano note le posizioni di tutti i suoi elementi –Sintassi: si specifica il nome del vettore senza parentesi int MyArray[ 24 ]; MyFunction(MyArray, 24 ); Di solito, alla funzione si passa anche la dimensione del vettore Va passata la dimensione se nel prototipo/definizione è richiesta E richiesta quando viene usata dentro la funzione (in pratica quasi sempre)
2000 Prentice Hall, Inc. All rights reserved Passare i vettori alle funzioni (2/4) Esiste un modo per passare un intero vettore per valore –Si deve anteporre parola chiave const al tipo del parametro presente nella definizione della funzione Passare gli elementi dei vettori come parametri di funzioni –Gli elementi sono invece passati per valore, come qualsiasi altra variabile –Ancora una volta, la funzione lavora su una copia dellelemento originale Le modifiche sul parametro dentro la funzione non hanno effetto sulloriginale –Sintassi: MyFunction2(MyArray[3]); Sintassi nel prototipo della funzione funzione void ModifyArrays(int b[], int DimensioneVettore); –Il nome del vettore va seguito da [] proprio per indicare che è un vettore –Nel prototipo, come al solito si possono omettere i nomi dei parametri int b[] potrebbe semplicemente essere int [] int DimensioneVettore potrebbe semplicemente essere int –Nella definizione, come al solito invece i nomi dei parametri vanno messi
2000 Prentice Hall, Inc. All rights reserved Passare i vettori alle funzioni (3/4) 1/* Fig. 6.13: fig06_13.c - Passare alle funzioni vettori/elementi */ 2#include 3#define SIZE 5 4 5void modificaVettore( int [], int ); 6void modificaElemento( int ); 7 8int main(){ 9 int a[ SIZE ] = { 0, 1, 2, 3, 4 }, i; printf( "Effetti del passare un intero vettore per riferimento:" 12 "\n\nI valori del vettore originale sono:\n" ); 13 for ( i = 0; i <= SIZE - 1; i++ ) printf( "%3d", a[ i ] ); 14 printf( "\n" ); 15 modificaVettore( a, SIZE ); /* passaggio per riferimento */ 16 printf( I valori del vettore modificato sono:\n" ); 17 for ( i = 0; i <= SIZE - 1; i++ ) 18 printf( "%3d", a[ i ] ); 19 printf( "\n\n\nEffetti del passare un elemento di un vettore " 20 per valore:\n\nIl valore di a[3] è %d\n", a[ 3 ] ); 21 modificaElemento( a[ 3 ] ); /* passaggio per valore */ 22 printf( Il valore di a[ 3 ] è %d\n", a[ 3 ] ); 23 return 0; 24} 1. Dichiarazione delle funzioni 2. Passa il vettore ad una funzione 3. Passa un elemento ad una funzione Lintero vettore passato per chiamata per riferimento e può essere modificato Lelemento del vettore passato attraverso una chiamata per valore e non può essere modificato
2000 Prentice Hall, Inc. All rights reserved Passare i vettori alle funzioni (4/4) 25 26void modificaVettore( int b[], int size ){ 27 int j; for ( j = 0; j <= size - 1; j++ ) b[ j ] *= 2; 30} 31 32void modificaElemento( int e ){ 33 printf( Il valore in modifyElement è %d\n", e *= 2 ); 34} Effetti del passare un intero vettore per riferimento: I valori del vettore originale sono: I valori del vettore modificato sono: Effetti del passare un elemento di un vettore per valore: Il valore di a[3] è 6 Il valore in modificaElemento è 12 Il valore di a[3] è 6 4. Definizioni delle funzioni Visualizzazione del programma
2000 Prentice Hall, Inc. All rights reserved Ordinare i vettori Lordinamento di dati –E unoperazione molto importante e frequente nelle applicazioni –Molto spesso le organizzazione devono ordinare dati E in genere devono ordinare grosse quantità di dati –Esistono molti algoritmi di ordinamento dei dati, ma ne vedremo uno solo Bubble Sort (ordinamento a bolle) –E un algoritmo di ordinamento che effettua numerose passate del vettore Passata significa scansione dellintero vettore con accesso ad ogni elemento Alla fine di ogni passata si otterrà un ordinamento parziale intermedio –Ad ogni passata, si confrontano coppie successive di elementi Se i 2 dati sono già in ordine (o sono uguali), non si attua nessun cambiamento Se non sono in ordine, i 2 elementi vengono scambiati –Esempio (ordinamento crescente): Vettore originale: Passata 1: Ha scambiato la coppia (4,2) Passata 2: Ha scambiato la coppia (3,2) Gli elementi più piccoli/leggeri pian piano emergono (scendono di posizione) –Su N dati, fa sempre N-1 confronti ad ogni passata e in totale N-1 passate Se il vettore è già ordinato con meno di N-1 passate, le fa tutte comunque
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (1/7) Media: è il valor medio calcolato su una serie di dati –Si ottiene dalla somma degli elementi del vettore diviso il numero di elementi –1, 2, 3, 4, 5, 6, 7, 8, 9 La media su questi dati è 5 Mediana: è il numero nel mezzo di una sequenza ordinata –Si ordina il vettore e si prende lelemento in posizione centrale (dimensione/2) –1, 2, 3, 4, 5 La mediana su questi dati è 3 Moda: è il numero che ricorre più frequentemente nella serie –1, 1, 1, 2, 3, 3, 4, 5 La moda su questi dati è 1
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (2/7) 1/* Fig. 6.16: fig06_16.c - Calcola media, mediana e moda dei dati */ 2#include 3#define SIZE void trovaMedia( const int [] ); 6void trovaMediana( int [] ); 7void trovaModa( int [], const int [] ) ; 8void bubbleSort( int [] ); 9void stampaVettore( const int [] ); 10 11int main(){ 12 int frequenze[10] = { 0 }; 13 int vettoreDati[SIZE] = 14 { 6, 7, 8, 9, 8, 7, 8, 9, 8, 9, 7, 8, 9, 5, 9, 8, 7, 8, 7, 8, 15 6, 7, 8, 9, 3, 9, 8, 7, 8, 7, 7, 8, 9, 8, 9, 8, 9, 7, 8, 9, 16 6, 7, 8, 7, 8, 7, 9, 8, 9, 2, 7, 8, 9, 8, 9, 8, 9, 7, 5, 3, 17 5, 6, 7, 2, 5, 3, 9, 4, 6, 4, 7, 8, 9, 6, 8, 7, 8, 9, 7, 8, 18 7, 4, 4, 2, 5, 3, 8, 7, 5, 6, 4, 5, 6, 1, 6, 5, 7, 8, 7 }; trovaMedia( vettoreDati ); 21 trovaMediana( vettoreDati ); 22 trovaModa( frequenze, vettoreDati ); 23 return 0; 24} 1. Prototipi delle funzioni 2. Inizializza i vettori 3. Chiama le funzioni per il calcolo di media, mediana e moda
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (3/7) 4. Definizione della funzione che calcola la media 5. Calcolo della media 6. Stampa della media 7. Definizione della funzione che calcola la mediana 8. Chiama la funzione che stampa larray originale 9. Chiama la funzione che ordina larray 10. Chiama la funzione che stampa larray ordinato 11. Visualizza lelemento in posizione SIZE/ void trovaMedia( const int vettore[] ){ 27 int j, totale = 0; printf( "%s\n%s\n", "Media", "********" ); 30 for ( j=0; j<=SIZE-1; j++ ) totale += vettore[j]; 31 printf( La media è uguale alla somma totale degli elementi" 32 \ndiviso per il numero di elementi ( %d ).\n" 33 Qui la media vale: %d / %d = %.4f\n\n, 34 SIZE, totale, SIZE, (double) totale / SIZE ); 35} 36 37void trovaMediana( int vettore[] ){ 38 printf( "\n%s\n%s\n%s", "Mediana", "********", 39 Il vettore con i dati non ordinati è:" ); 40 stampaVettore( vettore ); 41 bubbleSort( vettore ); 42 printf( "\n\nIl vettore ordinato è:" ); 43 stampaVettore( vettore ); 44 printf( "\n\nLa mediana è lelemento %d del vettore " 45 "ordinato.\nQui la mediana vale: %d\n\n", 46 SIZE / 2, SIZE, vettore[SIZE/2] ); 47} 48
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (4/7) 12. Definizione della funzione che calcola la moda 13. Ciclo di incremento dei contatori delle occorrenze, che son dati dagli elementi del vettore delle frequenze 14. Ad ogni giro incrementa il contatore che si trova in posizione pari al dato preso dal vettore 15. Stampa un istogramma con gli asterischi che indicano il numero di occorrenze di ogni dato 16. Funziona perchè si usa larray delle frequenze dalla seconda posizione in poi, saltando lindice 0 49void trovaModa( int freq[], const int vettore[] ){ 50 int dato, j, h, maxFreq = 0, moda = 0; printf( "%s\n%s\n", "Moda", "********" ); 53 for ( dato=1; dato<=9; dato++ ) freq[dato] = 0; 54 for ( j=0; j<=SIZE-1; j++ ) ++freq[ vettore[j] ]; 55 printf( "%s%11s%19s\n\n%54s\n%54s\n\n", 56 Elemento", "Frequenza", Istogramma", 57 " ", " " ); 58 for ( dato=1; dato<=9; dato++ ){ 59 printf( "%8d%11d ", dato, freq[dato] ); 60 if ( freq[dato] > maxFreq ){ 61 maxFreq = freq[dato]; 62 moda = dato; 63 } 64 for ( h=1; h<=freq[dato]; h++ ) 65 printf( "*" ); 66 printf( "\n" ); 67 } 68 printf( La moda è lelemento più ricorrente nel vettore.\n" 69 Qui la moda è %d che nel vettore è presente ben" 70 " %d volte.\n", moda, maxFreq ); 71} La stampa degli asterischi dipende dal valore di freq[] Da notare che lelemento di freq[] è sempre un valore di un elemento di vettore[]
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (5/7) 17. Definizione della funzione che ordina il vettore 18. Ciclo per fare le SIZE-1 passate del vettore 18. Ciclo interno per fare i SIZE-1 confronti per ogni passata del vettore 19. Usa una variabile apposta per salvare uno dei due valori da scambiare, in modo da non perderlo nello scambio 20. Definizione della funzione che stampa il vettore 72 73void bubbleSort( int vettore[] ){ 74 int pass, j, temp; for ( pass=1; pass<=SIZE-1; pass++ ) 77 for ( j=0; j<=SIZE-2; j++ ) 78 if ( vettore[ j ] > vettore[ j + 1 ] ){ 79 temp = vettore[ j ]; 80 vettore[ j ] = vettore[ j + 1 ]; 81 vettore[ j + 1 ] = temp; 82 } 83} 84 85void stampaVettore( const int vettore[] ){ 86 int j; for ( j=0; j<=SIZE-1; j++ ){ 89 if ( j % 20 == 0 ) printf( "\n" ); 90 printf( "%2d", vettore[ j ] ); 91 } 92} Bubble sort: se gli elementi sono fuori ordine, li scambia.
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (6/7) Media ******** La media è uguale alla somma totale degli elementi diviso per il numero di elementi (99). Qui la media vale: 681 / 99 = Mediana ******** Il vettore con i dati non ordinati è: Il vettore ordinato è: La mediana è lelemento 49 del vettore ordinato. Qui la mediana vale: 7 Visualizzazione del programma
2000 Prentice Hall, Inc. All rights reserved Caso di studio: calcolare media, mediana e moda usando i vettori (7/7) Mode ******** Elemento Frequenza Istogramma * 2 3 *** 3 4 **** 4 5 ***** 5 8 ******** 6 9 ********* 7 23 *********************** 8 27 *************************** 9 19 ******************* La moda è lelemento più ricorrente nel vettore. Qui la moda è 8 che nel vettore è presente ben 27 volte. Visualizzazione del programma
2000 Prentice Hall, Inc. All rights reserved Ricerca nei vettori: ricerca lineare e ricerca binaria (1/2) Cercare un valore chiave in un vettore –Si può trovare il valore chiave con algoritmi di ricerca lineare o binaria Ricerca lineare –Scandisce tutto il vettore confrontando ogni elemento col valore chiave Prosegue la scansione e fa confronti finchè non trova il valore chiave –E un algoritmo molto semplice, utile per vettori piccoli e disordinati Ha complessità lineare, ovvero nel caso peggiore richiede N confronti, su un vettore di N elmenenti Ricerca binaria –E un algoritmo utilizzabile solo su vettori già ordinati –Si confronta lelemento di mezzo (posizione N/2) del vettore con la chiave Se sono uguali, allora il valore voluto è stato trovato Se chiave < mezzo, cerca allo stesso modo nella sola prima metà del vettore Se chiave > mezzo, cerca allo stesso modo nella sola seconda metà del vettore Si continua a ripetere questa strategia su vettori man mano sempre più piccoli con la certezza che il valore chiave non è mai nelle parti di vettore scartate –Molto veloce, fa al massimo P passi, dove P è lintero superiore a log (N) Per un vettore di 30 elementi servono al massimo 5 passi, perchè 5 > log (30) 2 2
2000 Prentice Hall, Inc. All rights reserved Ricerca nei vettori: ricerca lineare e ricerca binaria (2/2) Funzione di ricerca lineare Funzione di ricerca binaria (avendo larray già ordinato) 1int ricercaBinaria( const int vettore[], int chiave, int size ){ 2 int posMin = 0, posMax = size-1, posMedia; 3 while (posMin <= posMax ){ /* Ad ogni giro, larray è ridotto */ 6 else if ( vettore[posMedia] > chiave ) posMax = posMedia - 1; 7 else posMin = posMedia + 1; 8 } /* Ritorna la posizione del valore trovato */ 10} 4 posMedia = (posMin + posMax ) / 2; 5 if ( vettore[posMedia] = = chiave ) return posMedia; /* Trovato! */ 9 return -1; /* Valore chiave non trovato */ 1int RicercaLineare( const int vettore[], int chiave, int size ){ 3 for (i=0; i<size; i++ ){ 5 } /* Ritorna la posizione del valore trovato */ 6 return -1; /* Valore chiave non trovato */ 7}7} 4 if ( vettore[i] == chiave ) return i; /* Trovato! */ 2 int i;
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (1/6) Vettori multidimensionali –Implementano tabelle con righe e colonne (vettore m per n ) –Si accede agli elementi specificando indice di riga e di colonna (matrici) printf( "%d", b[ 0 ][ 1 ] ); –Per il resto, i loro elementi vanno trattati come quelli di normali vettori –Si può anche ricavare larray monodimensionale di una riga della matrice int b[] = a[1]; Ora b contiene i valori in a[1][0], a[1][1], a[1][2], a[1][3] Inizializzazione int c[ 2 ][ 2 ] = { { 1, 2 }, { 3, 4 } }; –Gli inizializzatori sono raggruppati per riga tra { } più interne –Tutti gli elementi non inizializzati assumono valore 0 come al solito int c[ 2 ][ 2 ] = { { 1 }, { 3, 4 } }; Riga 0 Riga 1 Riga 2 Colonna 0Colonna 1Colonna 2Colonna 3 a[0][0] a[1][0] a[2][0] a[0][1] a[1][1] a[2][1] a[0][2] a[1][2] a[2][2] a[0][3] a[1][3] a[2][3]
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (2/6) Passare le matrici come parametri –Nel prototipo e nella definizione di funzioni, si deve sempre specificare la dimensione relativa alle colonne in modo esplicito int funzione1( int [][ SIZE ], int, int ); int funzione1( int matrice1[ ][ SIZE ], int righe, int colonne){ …. } –Come per i normali vettori, la matrice è passata di default per riferimento –Se si vuole passare la matrice per valore, si deve usare const int funzione1( const int [][ SIZE ], int, int ); –Si può passare anche unintera riga di una matrice, mai una colonna funzione( matrice[ riga ], SIZE ); Esempio duso classico: i menu testuali char menuOperazioni [4][50]={ {"1) Carica array con numeri casuali"}, {"2) Ricerca del massimo"}, {"3) Calcola la media"}, {"0) Esci dal programma"} }; –Attenzione ai limiti del vettore, la dimensione delle colonne deve essere sufficiente a contenere la stringa più lunga del menu
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (3/6) 1/* Fig. 6.22: fig06_22.c - Esempio di matrice */ 2#include 3#define STUDENTI 3 4#define ESAMI 4 5 6int minimo( const int [][ ESAMI ], int, int ); 7int massimo( const int [][ ESAMI ], int, int ); 8double media( const int [], int ); 9void stampaArray( const int [][ ESAMI ], int, int ); 10 11int main(){ 13 int studente; 14 const int votiStudenti[ STUDENTI ][ ESAMI ] = 15 { { 77,68,86,73 }, { 96,87,89,78 }, { 70,90,86,81 } }; printf( Il vettore dei voti è:\n" ); 18 printArray( votiStudenti, STUDENTI, ESAMI ); 19 printf( "\n\nIl voto più basso è: %d\nIl voto più alto è: %d\n", 20 minimo( votiStudenti, STUDENTI, ESAMI ), 21 massimo( votiStudenti, STUDENTI, ESAMI ) ); 22 for ( studente=0; studente<=STUDENTI-1; studente++ ) 23 printf( Il voto medio per lo studente %d è %.2f\n", 24 studente, media(votiStudenti[studente], ESAMI ) ); 25 return 0; 26} 1. Prototipi delle funzioni 2. Inizializzazione del vettore bidimensionale 3. Chiama la funzione che stampa la matrice 4. Stampa il voto più alto e il più basso tra tutti gli esami/studenti chiamando le funzioni per cercare tali voti 5. Stampa la media degli studenti chiamando la funzione che le calcola Ciascuna riga è un particolare studente e ogni colonna dà i suoi voti negli esami
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (4/6) 27 28/* Cerca il voto minimo nel vettore */ 29int minimo( const int voti[][ESAMI], int alunni, int risultati ){ 30 int i, j, votoMinimo = 100; for ( i=0; i<=alunni-1; i++ ) 33 for ( j=0; j<=risultati-1; j++ ) 34 if ( voti[i][j] < votoMinimo ) votoMinimo = voti[i][j]; 35 return votoMinimo; 36} 37 38/* Cerca il voto massimo */ 39int massimo( const int voti[][ESAMI], int alunni, int risultati ){ 40 int i, j, votoMassimo = 0; for ( i=0; i<=alunni-1; i++ ) 43 for ( j=0; j<=risultati-1; j++ ) 44 if ( voti[i][j] > votoMassimo ) 45 votoMassimo = voti[i][j]; 46 return votoMassimo; 47} Scandisce la matrice e se trova un valore più piccolo del minimo corrente questo diventa il nuovo valore minimo 7. Scandisce la matrice e se trova un valore più grande del massimo corrente questo diventa il nuovo valore massimo
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (5/6) 66} 51 int i, totale = 0; for ( i=0; i<=risultati-1; i++ ) totale += voti[i]; 54 return (double) totale / risultati; 55} 56 57/* Visualizza questo vettore */ 58void stampaArray(const int voti[][ESAMI], int alunni, int risultati){ 59 int i, j; printf( [0] [1] [2] [3]" ); 62 for ( i=0; i<=alunni-1; i++ ){ 63 printf( "\nVOTI[%d] ", i ); 64 for ( j=0; j<=risultati-1; j++ ) printf( "%-5d", voti[i][j] ); 65 } 49/* Determina il voto medio per un particolare studente */ 50double media(const int voti[], int risultati){ 8. Scandisce il vettore passato che contiene un riga della matrice (quindi i soli voti di un certo studente) per calcolarne la media 9. Ciclo che stampa a video la matrice dei voti di ogni studente
2000 Prentice Hall, Inc. All rights reserved Vettori multidimensionali (6/6) Il vettore dei voti è: [0] [1] [2] [3] VOTI[0] VOTI[1] VOTI[2] Il voto più basso è: 68 Il voto più alto è: 96 La media dei voti per lo studente 0 è La media dei voti per lo studente 1 è La media dei voti per lo studente 2 è Visualizzazione del programma