Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
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
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.