ALGORITMO DI EUCLIDE PER IL CALCOLO DEL MASSIMO COMUN DIVISORE Dati: INPUT a,b, (coppia di numeri interi) >= 0 OUTPUT mcd (numero intero) >=0 Proprietà: 1. Se a=b mcd(a,b)=a=b 2. Se a>b mcd(a,b)=mcd(a-b, b) 3. Se a<B mcd(a,b)=mcd(a, b-a) Considerazioni: La prima proprietà afferma che il massimo comun divisore di (a,b) è proprio a oppure b. Le altre due proprietà affermano che il mcd di (a,b) si può ricondurre al calcolo del massimo comun divisore di (a-b, b) oppure (a, b-a). Idea dell’algoritmo: Poiché valgono le proprietà precedenti, nel caso generale si possono calcolare tante differenze in modo da riportarsi al caso a=b, per il quale il problema è risolto. Il calcolo delle differenze deve essere ripetuto se risulta verificata la condizione a≠b. Si può utilizzare una iterazione a condizione iniziale (while …) Pseudocodifica: mentre (a≠b) while (a != b) se (a>b) if (a>b) a a-b a a-b altrimenti b b-a else b b-a fine mcd a mcd a CALCOLARE L’ENNESIMO NUMERO DI FIBONACCI Introduzione: La successione di Fibonacci è definita per n>=0 n=0 f(0)=0 n=1 f(1)=1 n>1 f(n)=f(n-1)+f(n-2) La successione di Fibonacci è una successione di interi: 0, 1, 1, 2, 3, 5, 8, 13, 21, … I primi due elementi sono 0 ed 1. L’elemento n-mo per n>=2 si ottiene sommando i 2 elementi precedenti. Dati: INPUT n (numero intero) >=0 OUTPUT fib (numero intero) >=0 VARIABILI fib1 (per memorizzare l’ultimo numero calcolato), fib2 (per memorizzare il penultimo numero calcolato), fib (per memorizzare il nuovo numero). Notazione lineare: Se (n == 0) Allora fib ← 0 Altrimenti Se if (n==1) Allora fib ← 1 Altrimenti { Calcola fib1, fib2 fib ← fib1 + fib2 inizializza contatore i con il valore 2 Mentre ( i < = n ) { calcola valore corrente di fib come somma dei 2 valori precedenti aggiorna penultimo valore calcolato fib2 aggiorna ultimo valore calcolato fib1 incrementa contatore i } Fine } Fine Fine Fine Pseudocodifica: /* Precondizione dell’algoritmo : n>=0 */ /* Postcondizione dell’algoritmo : fib >=0 */ if (n == 0) fib=0 else if (n==1) fib=1 else { fib2 =0 fib1 = 1 fib = 1 i=2 while ( i < = n ) { /* Asserzione invariante */ /* INV: (fib1 = fib) and (fib1= f(i-1) ) and fib2 = f( i-2) */ fib = fib1 + fib2 fib2 = fib1 fib1 = fib i = i +1 } } RIMOZIONE DEGLI ELEMENTI RIPETUTI DI UN ARRAY ORDINATO Introduzione: Consideriamo un insieme a di n elementi dello stesso tipo t. Il problema richiede di rimuovere i valori duplicati di a compattando gli elementi non duplicati. Esempio: INPUT a={10,20,20,40,50,50} n=4 OUTPUT a={10,20,40,50} n0=4 Dati: INPUT n (numero intero) >=0 a (vettore di n elementi) OUTPUT n0 (numero intero con n0>0 and n0<=n) a (vettore di n0 elementi) Premessa e conseguenza: PREMESSA a è un vettore di n elementi ordinato in senso non decrescente cioè a[i]<=a[i+1] per i che varia da 0 a (n-2) (N.B.: in a vi possono essere valori ripetuti) CONSEGUENZA a è un vettore composto da n0 valori non duplicati a[0]…a[n0-1] con n0<=n /* Precondizione dell’algoritmo */ /* PREC: n>0 and (a è un vettore di n elementi ordinato in senso non decrescente) */ /* Postcondizione dell’algoritmo */ /* POST: n0>0 and a è un vettore di n0 elementi aventi valori non duplicati */ Algoritmo: IDEA 10,20,20,40,50,50 Confrontare tutti gli elementi del vettore a coppie a[i] con a[i+1] – i varia da 0…n-2 Se la coppia in esame ha elementi diversi, spostare uno dei 2 elementi all’indietro, se vi sono posizioni libere. CONSIDERAZIONI 10,20,20,40,50,50 Il primo valore da spostare dovrebbe essere 40. Per fare lo spostamento è necessario conoscere fino a quale indice j gli elementi sono già stati compattati. Nell’esempio j=1 e 40 deve essere copiato nella posizione 2. L’algoritmo si può scrivere in due passi: 1. Ricerca della prima coppia di elementi duplicati – cioè trova l’indice j tale che tutti gli elementi del vettore di indici 0…j siano diversi tra loro. 2. Analizza gli elementi restanti – a partire da j – spostarli nelle posizioni occupate dai valori da eliminare. Pseudocodifica 1: /* Inizializza l’indice j mediante la ricerca della prima coppia di elementi duplicati */ i=0 while (i < n-1 & (la coppia a[i] e a[i+1] ha valori distinti) ) incrementa indice i j=i /* Asserzione: j>=0 and (gli elementi a[0]… a[j] hanno valori distinti) cioè a[0]..[j] è compattato*/ /* Sposta i valori degli elementi restanti nelle posizioni occupate dai valori da eliminare */ while ( i < n-1 ) { if la coppia a[i] e a[i+1] ha valori distinti { Incrementa j Sposta a[i+1] in a[j] } i = i +1 } } n0 = j+1 Pseudocodifica 2: /* Inizializza l’indice j mediante la ricerca della prima coppia di elementi duplicati */ i=0 while ( i < n-1 and (a[i] != a[i+1]) ) i=i+1 j=i /* Asserzione: j>=0 and (gli elementi a[0]… a[j] hanno valori distinti) cioè a[0]..[j] è compattato*/ /* Sposta i valori degli elementi restanti nelle posizioni occupate dai valori da eliminare */ while ( i < n-1 ) { if ( a[i] != a[i+1]) { j = j+1 // incrementa il numero j di elementi diversi a[j] = a [i+1]// sposta a[i+1] in a[j] } i = i +1 } } n0 = j+1 Codifica: /* Precondizione dell’algoritmo */ /* PREC: n>0 and (a è un vettore di n elementi ordinato in senso non decrescente) */ /* Postcondizione dell’algoritmo */ /* POST: n0>0 and a è un vettore di n0 elementi aventi valori non duplicati */ /* Ricerca della prima coppia di elementi duplicati */ i=0; while ( i < n-1 && a[i] != a[i+1] ) /* mentre (( vi sono coppie da esaminare ) and (la coppia di elementi i e i+1 ha valori distinti ) ) i=i+1; // incrementa indice i j=i ; /* Ass: j>=0 and (gli elementi a[0]… a[j] hanno valori distinti) */ /* Sposta i valori degli elementi restanti nelle posizioni occupate dai valori da eliminare */ while ( i < n-1 ) / * mentre vi sono ancora coppie da esaminare */ { if (a[i] != a[i+1] ) // la coppia di indici i e i+1 ha valori distinti { j=j+1; // incrementa il numero j di elementi diversi a[j] = a [i+1]; // sposta a[i+1] in a[j] } i = i +1 } n0= j+1; INVERSIONE DEGLI ELEMENTI DI UN ARRAY Introduzione: Sia a un vettore di n elementi. Si vuole invertire l’ordine degli elementi del vettore a (SENZA USARE UN VETTORE AUSILIARIO) Es: VETTORE DI INGRESSO 1 2 3 4 5 6 Es: VETTORE DI USCITA 6 5 4 3 2 1 Pseudocodifica: Calcoliamo l’indice dell’elemento centrale: m=parte intera (n/2) n pari: l’ultimo elemento da scambiare ha indice m-1 n dispari: l’elemento di indice m è centrale e non va scambiato anche in questo caso l’ultimo elemento da scambiare ha indice m-1 /*Pseudocodifica*/ Calcola m come parte intera (n/2) Itera per i che varia da 0 a m-1 Scambia a[i] e a[n-1-i] /* PRE: (a è un vettore di n elementi) and (n>0) */ /* POST: gli elementi di a sono in ordine inverso */ m = parte intera (n/2) for (i=0; i<m; i++) Scambia a[i] e a[n-1-i] Trace: Sia n= 8 a= 10, 20, 30, 40, 50, 60, 70,80 m= 8/2 = 4 i=0 a= 80, 20, 30, 40, 50, 60, 70, 10 i=1 a= 80, 70, 30, 40, 50, 60, 20,10 i=2 a= 80, 70, 60, 40, 50, 30, 20,10 i=3 a= 80, 70, 60, 50, 40, 30, 20,10 ALGORITMI DI RICERCA Consideriamo un insieme a di elementi dello stesso tipo t ed un valore x ti tipo t. Il problema della ricerca richiede di definire se il valore x appartiene oppure no all’insieme. ESEMPIO: a = {10,1,0,4,5} x = 100 La risposta è SI – x è stato trovato x = 100 La risposta è NO – x non è stato trovato Ipotesi: in a non vi sono valori ripetuti Analizziamo due diversi algoritmi di ricerca: ALGORITMO DI RICERCA LINEARE O ESAUSTIVA: non richiede alcuna ipotesi di ordinamento dei dati a ALGORITMO DI RICERCA BINARIA: si applica solo quando i dati a sono ordinati. RICERCA BINARIA o ESAUSTIVA (usare ALGORITMO do…while) Introduzione: L’idea dell’algoritmo si può sintetizzare come: scandire ogni elemento dell’insieme a e confrontarlo con il valore x da ricercare, iniziando dal primo elemento. Terminare la scansione di a appena il valore x viene trovato oppure non vi sono più elementi da analizzare. ALGORITMO (1° VERSIONE): mentre (x non viene trovato e vi sono ancora elementi da confrontare) confronta x con ogni elemento dell’insieme a Dati: INPUT n (numero intero) >0 a (vettore di n elementi di tipo t) x (valore di tipo t) OUTPUT trovato: {0, 1} ALGORITMO (ciclo while): trovato ← 0 i←0 Mentre (il valore x non è stato trovato ) and (vi sono altri elementi da esaminare) i ← i+1 Fine Se (a[i] uguale x) trovato ← 1 Fine /* L’ultimo controllo è necessario poiché la condizione di uscita dal ciclo è (x è stato trovato) or (non vi sono altri elementi da esaminare) */ ALGORITMO (ciclo while): trovato ← 0 i←0 while ( a[i] !=x && i<n-1) i ← i+1 if (a[i]==x) trovato ← 1 Condizione di uscita dal ciclo: a[i] ==x || i>=n-1 ALGORITMO (ciclo do…while): trovato ← 0 /* falso*/ i←0 do if A[i]==x trovato ← 1 /* vero */ i ← i+1 while (trovato ==0 && i < n) RICERCA DELL’INDICE DI UN VALORE X Introduzione: il problema della ricerca può richiedere di sapere se un valore x appartenga oppure no ad un vettore a e in caso affermativo quale posizione occupa. ESEMPIO a = {10,1,0,4,5} x = 400 La risposta è SI – x è stato trovato in posizione 3 x = 100 La risposta è NO – x non è stato trovato Dati: INPUT n (numero intero) >0 a (vettore di n elementi di tipo t) x (valore di tipo t) OUTPUT ind (di tipo int) ind>=0 se il valore viene trovato ind=-1 se x non viene trovato Codifica: trovato = 0; i = 0; ind -1; while ( a[i] !=x && i<n-1) i=i+1; if (a[i]==x) ind =i; RICERCA BINARIA Introduzione: A è un vettore di n elementi ordinati in senso crescente cioè A[i]<A[i+1] per i che varia 0 a (n-2). N.B.: in A non vi sono valori duplicati IDEA Confrontare il valore x con l’elemento centrale A[m] del vettore A e proseguire la ricerca a destra o a sinistra dell’elemento m in base all’esito del confronto. Pseudocodifica: trovato ← 0 Inizializza gli estremi dell’intervallo di ricerca –inf e sup While (inf <=sup) and (not trovato) Calcola la posizione centrale m=Parte intera[(inf+sup)/2] If x > A[m] inf ← m+1 Else If x < A[m] sup ← m-1 Else trovato ← 1 Legge e visualizza i valori di un vettore utilizza l'istruzione for #include <stdio.h> #define DIM 10 // dimensione del vettore int main() { int a[DIM]; int i, n; /* leggi n - numero di elementi n<=DIM */ printf("Numero di elementi del vettore, n<= %d ", DIM); scanf("%d",&n); if (n > DIM) { printf("errore nei dati\n"); } else { /* leggi vettore */ printf("inserire %d valori separati da spazi ",n); for (i=0;i<n;i++) { scanf("%d",&a[i]); } printf("\n"); /* SI PUO' INSERIRE IL CODICE PER ELABORARE a !!!!!!!!! */ ESERCIZI prof. ALTAMURA ORONZO Questo programma legge dimV elementi di tipo intero; le inserisce in un vettore e stampa il contenuto del vettore #include <stdio.h> #define dimV 10 //dimensione (numero massimo di elementi) del vettore V int main(){ int intero; int nV, //Numero effettivo del vettore i; //Variabile di controllo del ciclo int v[dimV]={0}; //Oppure potremmo nascondere l'istruzione iniziale #define dimV10 e scrivere, al posto di int v[dimV]={0}, int v[10]={0}; { int const FINE; //Variabile relativa al blocco {...} printf("\nLegge e scrive interi usando un ciclo while\n"); printf("\nLa terminazione dipende dal valore di fine definito durante l'esecuzione"); printf("\nNessun intero deve avere il valore di fine\n"); //Chiede di digitare il valore di fine printf("\nDigita il valore di fine\n"); scanf("%d", &FINE); printf("\nDigita gli interi separati da almeno uno spazio. "); printf("Per terminare digita %d e premi INVIO\n", FINE); nV=0; scanf("%d", &intero); //Ciclo di lettura while(intero!=FINE){ v[nV]=intero; nV++; scanf("%d", &intero); } /* visualizza vettore */ for (i=0;i<n;i++) { // printf("%d\n", a[i]); printf("%d ", a[i]); } } printf("\n"); system("pause"); return 0; //Ciclo di scrittura printf("\nElementi del vettore V: \n"); for (i=0; i<nV; i++) printf("%d ", v[i]); printf("\n"); } } system("pause"); return(0); } Legge dim elementi di tipo carattere, li inserisce in un vettore e li stampa #include <stdio.h> #define dimV 10 int main(){ char car; int nV, //Numero effettivo di elementi del vettore i; //Variabile di controllo del ciclo char v[dimV] = {' '}; //Vettore di massimo dimV caratteri inizializzato a ' ' //Lettura di una sequenza di caratteri printf("\nQuesto programma legge e scrive un vettore di caratteri"); printf("\nDigita una sequenza di massimo %d caratteri, non contente spazi", dimV); scanf("%c", &car); //Ciclo di lettura i=0; while ((car!=' ')&&(car!='\n')&&(i<dimV)){ v[i]=car; i++; scanf("%c", &car); } nV=i; //Definizione del numero effettivo di elementi del vettore V printf("\nNumero di caratteri letti = %d", nV); printf("\nLa sequenza dei caratteri letti e':"); for (i=0; i<nV; i++) printf("%c", v[i]); //Ciclo di stampa degli elementi del vettore V printf("%s", v); system("pause"); return 0; } ESERICIZIO RICAPITOLAZIONE Quesiti 31/10/2010 - Preparazione 1° Esonero 1) Contare il numero di volte in cui si ripete il valore MAX o il valore MIN in un vettore di n elementi. 2) Visualizza elementi vettore 3) Valutare l'ipotesi in cui i valori del vettore siano interi ad un intervallo[a,b], estremi inclusi, contare il numero di volte in cui si presentano nel vettore a i valori dell'intervallo ( cioè calcolare l'occorrenza di ogni valore dell'intervallo). 4) Contare il numero di elementi di un insieme che passiede una proprietà. 5) Leggere un numero non prefissato di interi di un vettore a di DIM elementi. 6) Uscire dal programma. #include <stdio.h> #define DIM 10 #define FineVettore -1 int main () { int n,i,a,b,scelta,vett[DIM],cont=0; do{ printf("\n\t\t\t*****ESERCIZI QUESITI*****"); printf("\n\n 1.Inserisci il numero massimo di elementi del vettore e gli elementi stessi"); printf("\n\n 2.Visualizza elementi vettore"); printf("\n\n 3.Contare il numero di volte in cui si presentano nel vettore i valori dell' intervallo impostato"); printf("\n\n 4.Contare il numero di elementi pari nel vettore"); printf("\n\n 5.Leggere un numero non prefissato di interi di un vettore a di DIM elementi."); printf("\n\n 6.Esci"); printf("\n\n\n\n Fai la tua scelta: "); scanf("%d",&scelta); switch(scelta){ /*1) Contare il numero di volte in cui si ripete il valore MAX o il valore MIN in un vettore di n elementi*/ case 1: Inserimento: printf("\n\n1.Inserisci il numero massimo degli elementi del vettore: "); scanf("%d",&n); if(n>DIM) {printf("\n\n\tATTENZIONE!!! LA DIMENSIONE MASSIMA DEL VETTORE E' %d\n",DIM); goto Inserimento;} else {for(i=0;i<n;i++){printf("\n\nInserisci l'elemento %d del vettore: ",i); scanf("%d",&vett[i]); }} break; /*2) Visualizza gli elementi del vettore*/ case 2: printf("\n\n2.Visualizza elementi del vettore: "); for(i=0;i<n;i++){printf("\n\nL'elemento %d del vettore e': %d",i,vett[i]);} break; /*3) Valutare l'ipotesi in cui i valori del vettore siano interi ad un intervallo[a,b], estremi inclusi, contare il numero di volte in cui si presentano nel vettore a i valori dell'intervallo ( cioè calcolare l'occorrenza di ogni valore dell'intervallo). */ case 3: printf("\n\n2.Inserisci il valore minimo del intervallo: "); scanf("%d",&a); printf("\n\n Inserisci il valore massimo del intervallo: "); scanf("%d",&b); /* Se l'elemento i del vettore è compreso nell'intervallo a e b allora si incrementa il contatore e stampiamo il numero e il numero di elementi*/ for(i=0;i<n;i++){if(vett[i]>=a && vett[i]<=b){printf("\n\nL'elemento %d e'compreso nell'intervallo:(%d,%d)",vett[i],a,b); cont++;}} printf("\n\nIl numero di elementi del vettore compresi nell'intervallo sono: %d",cont); break; /*4) Contare il numero di elementi pari.*/ case 4: for(i=0;i<n;i++){if(vett[i]%2==0) printf("\n\nL'elemento %d = %d e'pari",i,vett[i]);} break; /*5) Leggere un numero non prefissato di interi di un vettore vett di DIM elementi*/ case 5: i=0; /* Legge l'elemento 0 del vettore*/ printf("\n\nInserisci l'elemento %d del vettore(-1 per terminare): ",i); scanf("%d",&vett[i]); /* Mentre il vettore è diverso da -1 e minore della dimensione massima,aumenta l'indice del vettore e legge l'elemento i del vettore*/ while ((vett[i]!=FineVettore) && (i<DIM)){i++; printf("\n\nInserisci l'elemento %d del vettore: ",i); scanf("%d",&vett[i]);} printf("\n\nNumero di elementi del vettore:%d\n",i); /* Esci premendo 6 come scelta*/ case 6: break; default: printf("\n\nATTENZIONE SCELTA ERRATA");} while(scelta!=6); system("PAUSE"); return 0; }