CORSO DI PROGRAMMAZIONE II

Slides:



Advertisements
Presentazioni simili
INFORMATICA Altre Istruzioni di I/O
Advertisements

RICORSIONE: DEFINIZIONI RICORSIVE
1 Automazione dellalgoritmo ricorsivo di permutazione eseguita da Mariano Melchiorri.
Uso avanzato di C.
Programma: main() { istruzioni } ; assegnazione condizione ciclo istruzione: ;
if (condizione.) { blocco_istruzioni } else
Calcolo del minimo comune multiplo (m.c.m.) Luigi Sante
Ricorsione Procedure e funzioni ricorsive. Definizioni Un oggetto si dice ricorsivo se è definito totalmente o parzialmente in termini di sé stesso La.
Linguaggio C++ Selezione.
Procedure e funzioni ricorsive
MATLAB.
Informatica Generale Marzia Buscemi
Un nuovo tipo di dati Gli array.
La ricorsione Simulazione. Il Main /* Programma che usa una funzione ricorsiva*/ #include #define MAX_N 8 main() int valore, dato; printf(Introduci n:
TERNE PITAGORICHE Obiettivi dell’esercitazione
Introduzione agli algoritmi. Definizione Sistema di regole e procedure di calcolo ben definite che portano alla soluzione di un problema con un numero.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Esercizi su alberi binari
Tail recursion: esempio
Alberi binari Definizione della struttura dati: struct tree { };
Esercizi su alberi binari di ricerca
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2007/2008 Corso di Programmazione 1 a.a.2007/2008 Prof.ssa Chiara Petrioli Corso di Laurea.
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2007/2008 Prof.ssa Chiara Petrioli Corso di Laurea.
Informatica 2. Concetti fondamentali di programmazione Programmare vuol dire scrivere un algoritmo in un linguaggio che faccia funzionare un calcolatore.
Laboratorio di Linguaggi lezione IX: Dentro le Librerie Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese.
1 Corso di Informatica (Programmazione) Esercitazione 2 (3 dicembre 2008)
INTRODUZIONE ALLA PROGRAMMAZIONE STRUTTURATA
CORSO DI PROGRAMMAZIONE II Introduzione alla ricorsione
CORSO DI PROGRAMMAZIONE II
1 Lezione XIII Lu 17-Nov-2005 Programmare le classi.
APPUNTI SUL LINGUAGGIO C
ITERAZIONE e RICORSIONE (eseguire uno stesso calcolo ripetutamente) ITERAZIONE: ripetere piu volte una sequenza di operazioni istruzioni: for, while, do.
ITERAZIONE e RICORSIONE (eseguire uno stesso calcolo ripetutamente)
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Semantica Operazionale Strutturata
INFORMATICA Altre Istruzioni di I/O. © Piero Demichelis 2 Funzioni di I/O Per la lettura e la scrittura da videoterminale il C prevede numerose istruzioni.
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
La Programmazione Ricorsiva
Java Collections.
1.Scrivere una funzione per cercare un numero x in una lista circolare di interi. La funzione deve restituire NULL se il numero non esiste. 2.Scrivere.
CODIFICA Da flow-chart a C++.
Lezione 6 Strutture di controllo Il condizionale
void binario(int n); …………………
Lordinamento di tre numeri interi. acquisisci a,b,c (a > b) AND (a > c)(b > a) AND (b > c) (c > a) AND (c > b) Scrivi c,b,aScrivi b,c,aScrivi c,a,bScrivi.
Programmazione di Calcolatori
Esercizi Liste.
Registro a scorrimento
Tail recursion: esempio
Esercizi La distanza di hamming tra due interi x e y si definisce come il numero di posizioni nella rappresentazione binaria di x e y aventi bit differenti.
Esercizi su alberi binari di ricerca
Ricerca sequenziale in un array di interi
ND-partizione (A) n   A  somma  0 M  1/2 (  a i ) for i  1 to n do S[i]  choice ({true, false}) if S[i] then somma  somma + a i if somma > M then.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 2 La ricorsione Corso di Informatica 2 a.a. 2003/04 Lezione 2.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 5 Le strutture informative Corso di Informatica 2 a.a. 2003/04 Lezione 5.
ALGORITMI Un algoritmo è un insieme di istruzioni: -ordinate -non ambigue -effettivamente computabili.
Sistemi e Tecnologie Informatiche Ricorsione Umberto Ferraro Petrillo.
Le struct con il C. Cosa sono ? Variabili strutturate come i vettori … … ma che superano una limitazione dei vettori.
Corso JAVA Lezione n° 03 Istituto Statale di Istruzione Superiore “F. Enriques”
La ricorsione.
Flusso Statico e Dinamico 20/03/2006. Codice da Interpretare int valore; valore = funz(); if( valore > 0 ) { [codice1] } else { [codice2] } return valore;
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
Strutture di controllo Esercizi!. Utilizzare i metodi: I modi per poter richiamare un metodo, di una classe (ad esempio SavitchIn) sono due. 1) E’ sempre.
Informatica B Allievi Elettrici - AA Fondamenti della programmazione in linguaggio C (II) Istruzioni e strutture di controllo.
Allievi Elettrici - AA Le funzioni ricorsive in C
PROVA INTERCORSO MOD.B a.a RICORSIONE ESERCIZI A1.1-A1.6.
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
Informatica 4 La ricorsione. Definizione di ricorsione Ricorsione è la proprietà di quei programmi che, all’interno delle istruzioni che li compongono,
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su Alberi.
13. Strutture dati dinamiche Ing. Simona Colucci Informatica - CDL in Ingegneria Industriale- A.A
Transcript della presentazione:

CORSO DI PROGRAMMAZIONE II Lezione 7 Ricorsione su vettori prof. E. Burattini a.a. 2010-2011

RICORSIONE SU VETTORI Vogliamo ora mostrare come è possibile scorre un vettore A, mediante una funzione ricorsiva. Ad esempio: Assegnato un vettore A di interi, scrivere una funzione ricorsiva che ritorni true se ogni elemento del vettore A è diverso da K, false altrimenti.

Dal punto di vista iterativo un possibile algoritmo è il seguente: RICORSIONE SU VETTORI Consideriamo un vettore A di interi composto da n elementi come illustrato di seguito: Array di interi 3 6 12 -4 ….. A[i] …. 22 11 Indici 1 2 i ...... n-2 n-1 n   Dal punto di vista iterativo un possibile algoritmo è il seguente: Esso scorre il vettore per tutta la sua lunghezza controllando via via la parte rimanente. Non appena trova K esce altrimenti ritorna false bool diversodaK(int s[ ], int n, int K); { while (i<n && s[i]!=K) i++; return (s[i]!=K) }

Dal punto di vista ricorsivo possiamo immaginare che il controllo parta dall’indice n finale andando poi a ritroso. Dobbiamo ora determinare il caso in cui il processo termina, il caso base: se la chiamata ricorsiva raggiunge 0 senza trovare il valore K, allora la funzione deve ritornare true; se durante la chiamata ricorsiva si ritrova il valore K deve ritornare false altrimenti deve scendere di livello richiamando se stessa. bool diversodaK(int s[ ], int n, int K) { if ( n<0) return true; else if (s[n]==K) return false; else return diversodaK(s,n-1); } In definitiva si ha:

Variazioni sul tema della ricorsione Assegnato un vettore A di interi di dimensione N, calcolare in maniera ricorsiva la somma di tutti i suoi elementi. Per determinare tale somma osserviamo che se non ci sono elementi la somma vale 0; la somma dei primi N elementi è uguale alla somma di quelli precedenti più il valore attuale A[N]. Dalle osservazioni precedenti scaturisce subito il codice:

double sommaelementi(int a[], int N,int x) { if (x>=N) return 0; Precondizioni: x=0; double sommaelementi(int a[], int N,int x) { if (x>=N) return 0; else return a[x]+(sommaelementi(a,N,x+1)); } In questo algoritmo il caso base è determinato dal raggiungimento dell’indice x del valore N

Quando si applica un processo ricorsivo tipo quello della accumulazione bisogna assicurarsi che i valori accumulati nelle relative variabili siano correttamente passati da un processo all’altro. Inoltre il valore assunto da una variabile in un processo ricorsivo non deve essere distrutto dal lancio di un altro processo ricorsivo. Di qui la necessità di passare le variabili utilizzando la chiamata per riferimento.

Riscriviamo la funzione precedente con due variazioni: – utilizziamo una procedura e non una funzione; – scriviamo le somme parziali ogni 3 passi. In questo caso dobbiamo inserire nella lista dei parametri formali una variabile che ci consenta di mostrare la somma ogni 3 passi. // precondizioni: somma=0, i=0. void Sommarray2(int vet[], int N, int &somma, int i) { // somma elementi vettore mostrando le somme parziali ogni 3 if (i>N) somma=0; else { if (i%3==0) { cout<<"somma parziale "<<i<<" ="<<somma<<endl;} somma=somma+vet[i]; Sommarray2(vet, N,somma,i+1);} } Allegato: Ricorsione vettori

ESERCIZI. 1) Scrivere una funzione ricorsiva che, assegnati due interi N1 ed N2, restituisca la somma di tutti gli interi compresi tra N1 ed N2. Sia assegnato un vettore A di interi di dimensione N. Scrivere una funzione ricorsiva che calcoli il massimo valore tra gli elementi di A. Assegnato un vettore di caratteri S ed un carattere c, scrivere una funzione ricorsiva che calcoli le occorrenze di c in S. Assegnato un vettore D di dimensione N, scrivere una funzione ricorsiva che calcoli il minimo valore tra la differenza di ogni elemento con il precedente ( escluso il primo ). Assegnato un vettore F di dimensione N, scrivere una funzione ricorsiva che calcoli il massimo valore tra la somma di ogni elemento con il successivo ( escluso l’ultimo ).

Fino ad ora abbiamo considerato solo casi in cui erano presenti un solo caso base. E’ però possibile incontrare casi in cui ci sono due o più casi base. Mostreremo di seguito alcuni esempi.

Problema con due casi base. Assegnare agli elementi dell’Array di interi Ints, dei numeri interi positivi compresi nell’intervallo 1..Total. Ogni numero viene dato da tastiera. Il processo di lettura cessa o quando si introducono tutti i numeri previsti (Total) oppure quando si introduce un numero negativo. Subito dopo si effettua l’assegnazione. I CASI BASE possibili sono due: abbiamo letto il massimo numero possibile di valori abbiamo letto un numero negativo In entrambi i casi la lettura deve terminare e si esegue l’assegnazione.

// La ricorsione non lineare #include <iostream> Scriviamo l’algoritmo, tenendo presente che indichiamo con Left quanti numeri positivi è ancora possibile assegnare e con Temp il valore letto. // La ricorsione non lineare #include <iostream> #include "InsertArray.h" using namespace std; // PROTOTIPI void riempi(int, int &, int []); // MAIN int main() { int a[100],j,N,x,rimasti,nelementi; cout<<"Numeri di elementi "; cin>>nelementi; rimasti=0; riempi(nelementi, rimasti, a); stampa(a,rimasti); system("pause"); } // DEFINIZIONI void riempi(int nelementi, int &rimasti, int Ints[]) int Temp; if ((nelementi == 0)) return; else { cin>>Temp; if (Temp<=0) Ints[rimasti]=Temp; rimasti=rimasti+1; riempi(nelementi-1,rimasti,Ints); } //1° caso base //2° caso base //chiamata ricorsiva Allegato: ricorsione vettori

Sia dato un array A di caratteri di lunghezza L contenente ESERCIZIO Sia dato un array A di caratteri di lunghezza L contenente alcune parole separate da un trattino. Scrivere una funzione che restituisca TRUE se la prima parola è formata dai caratteri iniziali delle restanti parole. Esempio: L=24; A= PANE-PERA-AGO-NERO-ELICA L‘output sarà TRUE A= PANE-PERA-UGO-NERO-ELICA L‘output sarà FALSE bool elaboraIter(char a1[], int N1) { int i=0,j; bool trovato; while (a1[i]!='-') j=i; trovato=false; while ((j<N1)&&!trovato) if ((a1[j-1]=='-')&&(a1[j]==a1[i])) trovato=true; else j++; } if (!trovato) return false; i++; return true; Di lato riportiamo la versione iterativa

bool elaboraRic(char a1[], int N1, int i, int j) { if (a1[i]=='-') Questa è la versione ricorsiva. Si notino i due casi base e le due chiamate ricorsive. Il 1° caso base controlla il termine della lettura della prima parola, (quella di riferimento); Il 2° caso base interviene quando si è esplorato tutto il vettore senza trovare la parola che inizia con iI carattere previsto; La 1a chiamata ricorsiva si applica quando si è trovato un “-” seguito dall’iniziale della parola che coincide con il carattere richiesto, La 2a chiamata ricorsiva si applica quando non si è trovato il “-” //precondizioni i=0, j=1 bool elaboraRic(char a1[], int N1, int i, int j) { if (a1[i]=='-') return true; else if (j>N1) return false; if ((a1[j-1]=='-')&&(a1[j]==a1[i])) return elaboraRic(a1, N1, i+1,i); return elaboraRic(a1, N1, i,j+1); } ricorsVettoriCar

Altri esempi sono riportati nell’Allegato ricorsve3.cpp. Si noti che è allegata anche la libreria InsertArray.h che contiene una utility per la lettura dei vettori e una per la scrittura riportate di seguito. void LeggeVettore (int vet[],const int n, char nome, int nr, bool Acaso) { int i; if (Acaso){ //genera valori casuali for (i=0; i<n; i++) { vet[i]=fabs(rand()%10) ;//nr - nr/2; cout<<nome<<"["<<i<<"]="<<vet[i]<<" "; } cout<<endl;} else { cout<<"Assegna "<<n<<" valori"<<endl; //dati da tastiera cout<<nome<<"["<<i<<"]="; cin>>vet[i]; void StampaVettore (const int a[], const int n, char nome) { for (i=0; i<n; i++) { cout<<nome<<"["<<i<<"]="<<a[i]<<endl;

1 -1 1 RICORSIONE SULLE MATRICI Assegnata una matrice quadrata NxN, scrivere una funzione ricorsiva che restituisca true se la matrice è unitaria, false altrimenti. Come controlliamo ogni elemento della matrice? Partendo dalla riga=0 e colonna=0 possiamo procedere per linee orizzontali: quando la colonna arriva al valore n (nell’esempio N=3) allora scatta alla riga successiva e la colonna diventa 1: Se j>N allora i=i+1 e j=0 Caso Base: se i>N allora siamo giunti alla fine della matrice senza incontrare errori: la matrice è unitaria; se durante il controllo trova che la condizione non è verificata deve ritornare il valore false 1 1 -1

1 -1 1 RICORSIONE SULLE MATRICI Assegnata una matrice quadrata NxN, scrivere una funzione ricorsiva che restituisca true se la matrice è unitaria, false altrimenti. if i>N return true else if condizione NON vera return false else if j>N return unitaria (a,i+1,0,N) return unitaria(a,i,j+1,N) 1 Caso base: i>N Matrice unitaria Else è unitaria se altrimenti NON unitaria A[i,j]=1 se i=j A[i,j]=0 se i<>j 1 -1

1 -1 1 if i>N return true Caso base: i>N Matrice unitaria else if condizione NON vera return false else if j>N return unitaria (a,i+1,0,N) return unitaria(a,i,j+1,N) 1 Caso base: i>N Matrice unitaria Else è unitaria se altrimenti NON unitaria A[i,j]=1 se i=j A[i,j]=0 se i<>j 1 -1

RICORSIONE SULLE MATRICI Se la funzione ha il prototipo bool unitaria (int a[][10], int i, int j, int N) La sua definizione sarà: bool unitaria (int a[][colmax], int i, int j, int N) {if (i>N) return true; else if (((i==j) && (a[i][j]!=1)) || ((i!=j) && (a[i][j]!=0))) return false; if (j>N) return unitaria (a,i+1,0,N); return unitaria(a,i,j+1,N); }

Esercizi sulle matrici Assegnata una matrice A di interi scrivere una funzione ricorsiva che restituisca true se è simmetrica, false altrimenti. scrivere una procedura o funzione ricorsiva che restituisca il valore true se la matrice possiede due righe consecutive uguali, false altrimenti. scrivere una procedura ricorsiva che calcoli la somma delle righe dispari e quelle delle righe pari scrivere una funzione ricorsiva che restituisca true se tutti gli elementi della diagonale principale sono positivi scrivere una procedura o funzione ricorsiva che controlli se la somma degli elementi della diagonale principale è uguale a quella della diagonale secondaria scrivere una procedura o funzione ricorsiva che restituisca il valore true se ogni riga i-esima della matrice possiede un numero di i valori negativi, false altrimenti. Allegato: ricorsione matrici.cpp

bool simmetrica (int a[][colmax], int i, int j, int N) {if (i>N) ESEMPIO /* scrivere una funzione ricorsiva che restituisca true se è simmetrica, false altrimenti. */ bool simmetrica (int a[][colmax], int i, int j, int N) {if (i>N) return true; else if (j>N) return simmetrica(a,i+1,0,N); if (a[i][j]!=a[j][i]) return false; return simmetrica(a,i,j+1,N); }

bool righeUguali (int a[][colmax],int i, int j, int N ) { /* scrivere una funzione ricorsiva che restituisca il valore true se la matrice possiede due righe consecutive uguali, false altrimenti.*/ bool righeUguali (int a[][colmax],int i, int j, int N ) { if (i>N-1) return false; else if (j>N) return true; if (a[i][j]!=a[i+1][j]) return righeUguali(a,i+1,0,N); return righeUguali(a,i,j+1,N); } ESEMPIO

/*scrivere una procedura ricorsiva che calcoli la somma delle righe dispari e quelle delle righe pari*/ void pariDispari(int a[][cmax], int i, int j, int N, int &sommaP, int &sommaD) { if (i<=N) { if (j>N) return pariDispari(a,i+1,0,N,sommaP,sommaD); else if ((i%2)==0) sommaP=sommaP+a[i][j]; sommaD=sommaD+a[i][j]; return pariDispari(a,i,j+1,N,sommaP,sommaD); } } ESEMPIO void pariDispari(int a[][cmax], int i, int j, int N, int &sommaP, int &sommaD) { if (i<=N) { if (j>N) return pariDispari(a,i+2,0,N,sommaP,sommaD); else sommaP=sommaP+a[i][j]; sommaD=sommaD+a[i][j]; return pariDispari(a,i,j+1,N,sommaP,sommaD); } }

return (sommadP==sommadS);} else sommadP=sommadP+a[i][i]; /*scrivere una procedura o funzione ricorsiva che controlli se la somma degli elementi della diagonale principale è uguale a quella della diagonale secondaria*/ bool sommaDiag(int a[][colmax], int i, int N, int &sommadP, int &sommadS) { if (i<0){ return (sommadP==sommadS);} else sommadP=sommadP+a[i][i]; sommadS=sommadS+a[i][N-1-i]; return sommaDiag(a,i-1,N,sommadP,sommadS); } ESEMPIO

bool iesimo(int a[][colmax], int i, int j,int N, int &sommaneg) { /*scrivere una procedura o funzione ricorsiva che restituisca il valore true se ogni riga i-esima della matrice possiede un numero di i valori negativi, false altrimenti.*/ bool iesimo(int a[][colmax], int i, int j,int N, int &sommaneg) { if (i<0) return true; else if (j<0) { if (sommaneg!=i) return false; sommaneg=0; return iesimo(a,i-1,N,N,sommaneg); } else { if (a[i][j]<0 ) sommaneg=sommaneg+1; if (sommaneg>i) return false; return iesimo(a,i,j-1,N,sommaneg);} return iesimo(a,i,j-1,N,sommaneg); } ESEMPIO ricorsione matrici

ESERCIZIO /* Assegnata una matrice MxM determinare, con una funzione ricorsiva, se ci sono due righe uguali anche non consecutive. */ il valore massimo tra i massimi delle diagonali principali. */

Esercizio Assegnata una matrice A NxM scrivere una funzione booleana ricorsiva che verifichi che a partire dall’elemento A[0][0] ad ogni coppia di indici la cui somma è pari corrisponda un elemento della matrice pari e dispari in caso contrario. Verificare anche che leggendo la matrice per righe, i numeri pari siano disposti in maniera crescente e i dispari in maniera decrescente. Es. TRUE A= perché A[0][0]=pari, … ,A[0][3]=dispari, la sequenza dei pari cresc (2, 6, 8, 12,14,18) mentre quella dei dispari decresce (15, 13, 11, 9, 7,3) 2 15 6 13 11 8 9 12 14 7 18 3