La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Algoritmi su Array Moreno Marzolla

Presentazioni simili


Presentazione sul tema: "Algoritmi su Array Moreno Marzolla"— Transcript della presentazione:

1 Algoritmi su Array Moreno Marzolla
Dipartimento di Informatica—Scienza e Ingegneria (DISI) Università di Bologna

2 Copyright © 2008, Stefano Mizzaro
Copyright © 2016, 2017, Moreno Marzolla This work is licensed under the Creative Commons Attribution-Non Commercial 2.0 (CC BY-NC 2.0) License. To view a copy of this license, visit or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. Array

3 Ringraziamenti prof. Stefano Mizzaro, Università di Udine
Array

4 Esempi classici con array
Inversione Ricerca lineare Ricerca binaria Ordinamento Array

5 Inversione Array

6 Inversione di un array Scambiare di posto gli elementi di un array a[] di n elementi Il primo e l’ultimo Il secondo e il penultimo … (fermarsi a metà!!) Prima 7 12 3 -1 8 2 1 3 2 15 15 2 3 1 2 8 -1 3 12 7 Dopo Array

7 Inversione di un array Considero il primo e l'ultimo elemento e li scambio 7 12 3 -1 8 2 1 3 2 15 Array

8 Inversione di un array Considero il secondo e il penultimo elemento e li scambio 15 12 3 -1 8 2 1 3 2 7 Array

9 Inversione di un array ...e vado avanti così
Devo però fermarmi a metà dell'array! Perché? 15 12 3 -1 8 2 1 3 2 7 Array

10 L’algoritmo Prima versione Considero il primo e l’ultimo e li scambio
Considero il secondo e il penultimo e li scambio Fino a metà array "Pseudo"-pseudocodice i = 0; j = n-1; while ("non sono arrivato a metà") { "scambia a[i] con a[j]" i = i + 1; j = j – 1; } Array

11 Raffinamento Come decido se non sono ancora arrivato a metà? i j 7 12
3 -1 8 2 1 3 2 15 i j 7 12 3 -1 8 2 1 3 2 15 i = 0; j = n-1; while (i < j) { "scambia a[i] con a[j]" i = i + 1; j = j – 1; } Array

12 Come (non) scambiare il valore di due variabili
int a = 3, b = 5; /* modo SBAGLIATO di scambiare tra loro i valori di a e b */ a = b; b = a; Quale è il risultato del frammento di codice sopra? Array

13 Come scambiare il valore di due variabili
3 bicchieri, a, b e tmp ("temporaneo") In a c’è acqua, in b c’è vino, tmp è vuoto Voglio “scambiare” a e b (mettere il vino in a e l’acqua in b). Come faccio? a b tmp Array

14 Come scambiare il valore di due variabili
3 bicchieri, a, b e tmp ("temporaneo") In a c’è acqua, in b c’è vino, tmp è vuoto Voglio “scambiare” a e b (mettere il vino in a e l’acqua in b). Come faccio? Verso a in tmp a b tmp Array

15 Come scambiare il valore di due variabili
3 bicchieri, a, b e tmp ("temporaneo") In a c’è acqua, in b c’è vino, tmp è vuoto Voglio “scambiare” a e b (mettere il vino in a e l’acqua in b). Come faccio? Verso a in tmp Verso b in a a b tmp Array

16 Come scambiare il valore di due variabili
3 bicchieri, a, b e tmp ("temporaneo") In a c’è acqua, in b c’è vino, tmp è vuoto Voglio “scambiare” a e b (mettere il vino in a e l’acqua in b). Come faccio? Verso a in tmp Verso b in a Verso tmp in b a b tmp Array

17 Come scambiare il valore di due variabili
/* modo CORRETTO di scambiare tra loro i valori di a e b */ int a = 3, b = 5, tmp; tmp = a; /* “verso” a in tmp */ a = b; /* “verso” b in a */ b = tmp; /* “verso” tmp in a */ Array

18 Come scambiare due elementi di un array
Voglio “scambiare” a[i] e a[j]. Come faccio? tmp = a[i]; a[i] = a[j]; a[j] = tmp; 2. a[i] a[j] tmp 1. 3. Array

19 Inversione di un array /* inversione.c : inverte il contenuto di un array */ #include <stdio.h> void inverti(int a[], int n) { int i = 0, j = n-1, tmp; while ( i < j ) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; i++; j--; } #define N 10 int main( void ) int a[N], i; printf("Digita %d valori\n", N); for (i = 0; i < N; i++) { /* Lettura dell'array */ scanf("%d", &a[i]); inverti(a, N); for (i = 0; i < N; i++) { /* Stampa l'array dopo l'inversione */ printf("%d\n", a[i]); return 0; (così si legge in input un array) Array

20 Ricerca lineare Array

21 Ricerca lineare Dati Un array a[] di int La lunghezza n dell'array
Un intero k int ricerca(int a[], int n, int k) Restituisce la posizione di una occorrenza di k in a[] Se k non compare in a, restituisce -1 Procedimento Scorro l’array partendo dall’inizio Fermandomi se trovo un elemento il cui valore è uguale a k, oppure se arrivo in fondo all'array k 3 7 12 3 -1 8 2 1 3 2 15 a[] Array 1 2 3 4 5 6 7 8 9

22 Ricerca lineare Primo tentativo (sbagliato)
int ricerca(int a[], int n, int k) { int i; for (i = 0; i < n; i++) { if (a[i] == k) { "trovato" } else { "non trovato" } SBAGLIATO Con il while? k 3 a[] 7 12 3 -1 8 2 1 3 2 15 Array 1 2 3 4 5 6 7 8 9

23 Ricerca lineare Secondo tentativo (meglio)
int ricerca(int a[], int n, int k) { int i; for (i = 0; i < n; i++) { if (a[i] == k) { "trovato" } "non trovato" OK k 3 a[] 7 12 3 -1 8 2 1 3 2 15 Array 1 2 3 4 5 6 7 8 9

24 Ricerca lineare /* ricerca-lineare.c */ #include <stdio.h>
int ricerca(int a[], int n, int k) { int i; for (i = 0; i < n; i++) { if (a[i] == k) { return i; } return -1; int main( void ) int a[] = {7, 12, 3, -1, 8, 2, 1, 3, 2, 15}; printf("ricerca 7 = %d\n", ricerca(a, 10, 7)); printf("ricerca 15 = %d\n", ricerca(a, 10, 15)); printf("ricerca 3 = %d\n", ricerca(a, 10, 3)); printf("ricerca 17 = %d\n", ricerca(a, 10, 17)); return 0; Ricordare che l'istruzione return termina immediatamente l'esecuzione della funzione, restituendo il valore indicato Array

25 Una applicazione della ricerca lineare
Il sindaco di Paperopoli ha deciso di tassare i residenti in base al reddito. Detto R il reddito lordo annuo, l'importo dovuto in tasse è (R ´ x), dove x dipende da R secondo la seguente tabella Se 0 ≤ R < → x = 0.05 Se ≤ R < → x = 0.11 Se ≤ R → x = 0.15 Scrivere un programma in C che chiede all'utente di inserire il reddito R (tipo double; se l'utente inserisce un valore negativo, richiederlo), e stampa l'importo dovuto in tasse Array

26 Primo tentativo: funziona, ma...
/* tasse-1.c */ #include <stdio.h> int main( void ) { double R, x; do { printf("Inserire reddito R\n"); scanf("%lf", &R); } while (R < 0); if ( R < ) { x = 0.05; } else { if ( R < ) { x = 0.11; x = 0.15; } printf("Le tasse dovute ammontano a %f\n", R*x); return 0; Array

27 Un bel giorno... Vista la situazione disastrata delle finanze di Paperopoli, il sindaco decide di introdurre nuovi scaglioni: Se 0 ≤ R < → x = 0.05 Se ≤ R < → x = 0.11 Se ≤ R < → x = 0.15 Se ≤ R < → x = 0.17 Se ≤ R < → x = 0.20 Se ≤ R → x = 0.25 Modificare il programma precedente per funzionare correttamente nella nuova situazione Array

28 /* tasse-2.c */ #include <stdio.h> int main( void ) { double R, x; do { printf("Inserire reddito R\n"); scanf("%lf", &R); } while (R < 0); if ( R < ) { x = 0.05; } else { if ( R < ) { x = 0.11; if ( R < ) { x = 0.15; if ( R < ) { x = 0.17; if ( R < ) { x = 0.20; x = 0.25; } printf("Le tasse dovute ammontano a %f\n", R*x); return 0; Array

29 /* tasse-2.c */ #include <stdio.h> int main( void ) { double R, x; do { printf("Inserire reddito R\n"); scanf("%lf", &R); } while (R < 0); if ( R < ) { x = 0.05; } else { if ( R < ) { x = 0.11; if ( R < ) { x = 0.15; if ( R < ) { x = 0.17; if ( R < ) { x = 0.20; x = 0.25; } printf("Le tasse dovute ammontano a %f\n", R*x); return 0; Array

30 Idea Memorizzo gli scaglioni e le relative percentuali in una "tabella" Dato il reddito R, cerco nella "tabella" lo scaglione corrispondente e da questo ricava la percentuale Se gli estremi degli scaglioni e/o le percentuali cambiano, devo cambiare solo la tabella e non il programma che fa la ricerca! Array

31 Nuova soluzione: meglio
/* tasse-3.c */ #include <stdio.h> int main( void ) { const int nscaglioni = 6; double scaglioni[] = { 0.0, , , , , }; double imposta[] = {0.05, , , , , }; double R, x; int i; do { printf("Inserire reddito R\n"); scanf("%lf", &R); } while (R < 0); for (i=0; (i < nscaglioni) && (R >= scaglioni[i]); i++) { x = imposta[i]; } printf("Le tasse dovute ammontano a %f (imposta=%f%%)\n", R*x, x*100); return 0; scaglioni[i] è il limite inferiore dello scaglione i-esimo (inizio a contare da i = 0). imposta[i] è la percentuale di tasse per i redditi appartenenti allo scaglione i-esimo Array

32 Esercizio 6 cassetti di resistenze etichettati con i seguenti valori (in Ohm): 10, 15, 22, 33, 47, 68 I valori hanno una tolleranza di +/- 10% Significa. ad es., che il cassetto etichettato 15 può contenere resistenze con 15 ´ 0.9 ≤ R ≤ 15 ´ 1.1 Nota: gli intervalli NON si sovrappongono Data una resistenza di valore misurato R, determinare in quale cassetto deve essere riposta E' possibile che R sia tale da non poter essere inserito in alcun cassetto; in tal caso il programma lo deve segnalare ad es. con un opportuno messaggio d'errore Assumere che tutti i valori siano di tipo float Array

33 10 15 22 33 47 68 R = 21 Array

34 Possibile soluzione /* resistenza.c */ #include <stdio.h>
int main( void ) { const int n = 6; /* numero di cassetti */ float val[] = {10, 15, 22, 33, 47, 68}; float R; int i; printf("Inserire R\n"); scanf("%f", &R); for (i=0; i<n; i++) { if ( R >= val[i]*0.9 && R <= val[i]*1.1 ) break; } if ( i < n ) { printf("Resistenza R=%f nel cassetto etichettato %f\n", R, val[i]); } else { printf("Resistenza R=%f non inseribile in alcun cassetto\n", R); return 0; Array

35 Ricerca Binaria Array

36 Ricerca binaria Dati: Un array di valori reali distinti v[0], v[1], … v[n-1] ordinati in senso crescente (v[0] < v[1] < … < v[n-1]) Un valore reale k (arbitrario) Determinare la posizione di k nell'array (se presente) Cioè determinare l'indice i, se esiste, tale che v[i] == k Se k non compare nell'array, restituire -1 Es: v[0] v[1] v[2] v[3] v[4] v[5] v[6] v[7] Cerchiamo k = 13 -3 -1 2 5 6 13 15 21 Array La funzione restituisce 5 Vedere i lucidi sugli algoritmi

37 Funzionamento dell'algoritmo
Usiamo due valori interi i (inizio) e f (fine) per rappresentare la posizione (indice) del primo e dell'ultimo elemento della porzione di array in cui potrebbe trovarsi il valore cercato Indichiamo con m (mezzo) l'indice dell'elemento che occupa la posizione centrale nel sottovettore v[i] … v[f] i=0 m=3 f=6 v[0] v[1] v[2] v[3] v[4] v[5] v[6] 2 3 7 12 18 21 27 Cerchiamo k = 3 Algoritmi

38 Pseudocodice i = 0; f = n – 1; while (f ≥ i) { m = (i + f) / 2;
if (v[m] == k) { "trovato in posizione m" } else { if (v[m] > k) { f = m – 1; i = m + 1; } "non trovato" Algoritmi

39 /* ricerca-binaria.c */ #include <stdio.h>
int ricbinaria(int v[], int n, int k) { int i = 0, f = n-1, m; while (f >= i) { m = (i + f) / 2; if (v[m] == k) { return m; /* trovato in posizione m */ } else { if (v[m] > k) { f = m - 1; i = m + 1; } return -1; /* non trovato */ int main( void ) int a[] = {-1, 1, 2, 3, 7, 15, 16, 18, 20, 21}; printf("ricerca 7 = %d\n", ricbinaria(a, 10, 7)); printf("ricerca -1 = %d\n", ricbinaria(a, 10, -1)); printf("ricerca 17 = %d\n", ricbinaria(a, 10, 17)); printf("ricerca -2 = %d\n", ricbinaria(a, 10, -2)); return 0; Algoritmi

40 Cosa succede se l'array contiene valori duplicati?
/* ricerca-binaria.c */ #include <stdio.h> int ricbinaria(int v[], int n, int k) { int i = 0, f = n-1, m; while (f >= i) { m = (i + f) / 2; if (v[m] == k) { return m; /* trovato in posizione m */ } else { if (v[m] > k) { f = m - 1; i = m + 1; } return -1; /* non trovato */ int main( void ) int a[] = {-1, 1, 2, 3, 7, 15, 16, 18, 20, 21}; printf("ricerca 7 = %d\n", ricbinaria(a, 10, 7)); printf("ricerca -1 = %d\n", ricbinaria(a, 10, -1)); printf("ricerca 17 = %d\n", ricbinaria(a, 10, 17)); printf("ricerca -2 = %d\n", ricbinaria(a, 10, -2)); return 0; Cosa succede se la funzione ricbinaria() viene invocata su un array vuoto (n = 0)? Cosa succede se l'array contiene valori duplicati? Algoritmi

41 Ordinamento Algoritmi

42 Ordinamento Ordinare un array Problema classico
Capita spesso in moltissime applicazioni Vari algoritmi Ne vediamo uno (Selection Sort) Semplice da capire Non molto efficiente Array

43 Algoritmi e Strutture Dati
Selection Sort 12 7 3 2 14 22 1 3 1 7 3 2 14 22 12 3 Cerco il minimo in a[0]...a[n-1] e lo scambio con a[0] Cerco il minimo in a[1]...a[n-1] e lo scambio con a[1] ... Cerco il minimo in a[i]...a[n-1] e lo scambio con a[i] 1 2 3 7 14 22 12 3 1 2 3 7 14 22 12 3 1 2 3 3 14 22 12 7 1 2 3 3 7 22 12 14 1 2 3 3 7 12 22 14 Algoritmi e Strutture Dati 1 2 3 3 7 12 14 22

44 Algoritmi e Strutture Dati
Pseudocodice Prima versione Raffinamento for i ← 0 to n – 2 do "Determina il valore minimo v[j] del sottovettore v[i] .. .v[n – 1]" "Scambia v[i] con v[j]" endfor for i ← 0 to n–2 do for j ← i+1 to n–1 do if (a[i] > a[j]) then "scambia a[i] con a[j]" endif endfor Algoritmi e Strutture Dati

45 Algoritmi e Strutture Dati
12 7 3 2 14 22 1 3 i j 7 12 3 2 14 22 1 3 3 12 7 2 14 22 1 3 2 12 7 3 14 22 1 3 2 12 7 3 14 22 1 3 2 12 7 3 14 22 1 3 1 12 7 3 14 22 2 3 Algoritmi e Strutture Dati

46 Algoritmi e Strutture Dati
Costo computazionale Quante volte viene eseguito il blocco di codice evidenziato? for i ← 0 to n–2 do for j ← i+1 to n–1 do if (a[i] > a[j]) then "scambia a[i] con a[j]" endif endfor Il blocco viene eseguito (n-1) + (n-2) + … volte Algoritmi e Strutture Dati

47 Algoritmi e Strutture Dati
= una iterazione del ciclo "for" interno (quello con indice j) n - 1 i → 1 2 3 4 n-2 Algoritmi e Strutture Dati

48 Algoritmi e Strutture Dati
= una iterazione del ciclo "for" interno (quello con indice j) n - 1 n n - 1 i → 1 2 3 4 n-2 Algoritmi e Strutture Dati

49 Il codice /* selection-sort.c */ #include <stdio.h>
void selectionsort(int a[], int n) { int i, j, tmp; for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { if (a[i] > a[j]) { tmp = a[i]; /* scambio a[i] con a[j] */ a[i] = a[j]; a[j] = tmp; } #define N 10 int main( void ) int a[N], i; for (i = 0; i < N; i++) { scanf(“%d”, &a[i]); } selectionsort(a, N); for (i = 0; i < N; i++) { printf(“%d\n”, a[i]); } return 0; Array


Scaricare ppt "Algoritmi su Array Moreno Marzolla"

Presentazioni simili


Annunci Google