LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di...
-
Upload
susana-mariani -
Category
Documents
-
view
219 -
download
0
Transcript of LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di...
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 1
Linguaggi di programmazione ILa ricorsione
Prof. Luigi Di Lascio
Lezione 10
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 2
Funzioni Ricorsive
In particolare:La definizione ricorsiva di una funzione utilizza la funzione stessa e una versione più semplice di questa
a. 1 è un numero naturaleb. Il successore di un numero naturale è un
numero naturale
La definizione di un concetto matematico è detta ricorsivo se questo è definito (totalmente o parzialmente) in termini di se stesso
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 3
Esempio: la definizione ricorsiva del fattoriale di n
Se n=0 allora fat(n)=1
altrimenti fat(n)=n*fat(n-1)
1. 0!=1
2. n!=n*(n-1)!
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 4
long int fat(int n){ long int fattoriale; if(n==0) fattoriale=1; else fattoriale=n*fat(n-1); return fattoriale;}
Esempio: la definizione ricorsiva del fattoriale di n, l’implementazione
Se n=0 allora fat(n)=1
altrimenti fat(n)=n*fat(n-1)
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 5
Il proccesso ricorsivo
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 6
Come evidenziare il processo ricorsivolong int fat(int m) { long int fattoriale; if(m==0) fattoriale=1; else fattoriale=m*fat(m-1); printf("fattoriale(%d) = %d\n",m,fattoriale); return fattoriale; }
fattoriale(0) = 1fattoriale(1) = 1fattoriale(2) = 2fattoriale(3) = 6fattoriale(4) = 24fattoriale(5) = 120RIS. FINALE: fattoriale di 5 = 120Premere un tasto per continuare . . .
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 7
Definizioni ricorsive/1
Vita quotidiana (anzi serale e mangereccia)
L’ordine di una o più pizze può essere cosi formulata:
ordine := <pietanza> <conto>
ordine : = <pietanza> <ordine>
pietanza := margheritabruschetta vino
conto := somma da pagare
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 8
Definizioni ricorsive/2
Definizioni ricorsive di libro
libro := <capitolo>libro: = <capitolo> <libro><capitolo >:= qui definizione
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 9
Definizioni ricorsive/3
Definizioni ricorsive di libro, capitolo e paragrafo
libro := <capitolo>libro: = <capitolo> <libro>capitolo := <paragrafo>capitolo : = <paragrafo><capitolo>paragrafo : = <testo>paragrafo := <testo><paragrafo>testo := <parola>testo: = <parola><testo>parola:= una stringa presente sul vocabolario di italiano
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 10
Definizioni ricorsive: in generale /1
Se questo è il caso più semplice, allora calcola la soluzione, altrimenti ridefinisce il problema usando la ricorsione
Somma di n numeri interi
Parte ricorsiva: somma(n) = a[n-1]+somma(n-1)
Caso più semplice: la sequenza è costituita da un solo numero a[0]. In tal caso: somma = a[0]
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 11
La funzione ricorsiva somma(n)
long int somma(int a[], int dim){ if(dim==1) return a[dim-1]; else return (somma(a,dim-1)+a[dim-1]); }
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 12
Definizioni ricorsive: in generale /2
Se C è il caso più semplice, allora calcola la soluzione immediata, altrimenti ridefinisci il problema mediante suoi sottoproblemi, usando la ricorsione
Esempio: Definizione ricorsive di potenza di base b ed esponente intero positivo n: potenza(b,n)
Parte ricorsiva: ridefinire il problema mediante una definizione ricorsiva di più sottoproblemi:
potenza(b,n)=b*potenza(b,n-1)
Se n=0 allora potenza(b, 0) = 1, altrimenti potenza(b,n)=b*potenza(b,n-1)
Caso semplice: potenza(b, 0) = 1
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 13
La funzione ricorsiva potenza(b, n)
long int potenza(int base, int esp){ long int pot; /*printf("dati di input: base=%d, esp=%d\
n",base,esp);*/
if(esp==0) pot=1; else pot=base*potenza(base,esp-1); /*printf("potenza(%d, %d) = %d\n",base,esp,pot);*/ return pot;}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 14
Permutazioni, disposizioni, combinazioni
Disposizioni semplici di n oggetti distinti presi k a kDn,k = n (n 1) (n 2) ... (n k + 2) (n k + 1)=
n!/(n-k)!
Permutazioni semplici di n oggetti distinti
P(n) = n!
Combinazioni semplici di n oggetti distinti presi k a kCn,k = Dn,k/k!=n!/(k!(n-k)!)
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 15
Disposizioni
Disposizioni semplici di n oggetti distinti presi k a k2. D(n, k) = n!/(n-k)! = n*(n-1)!/[(n-1)-(k-1)]=n*D(n-1, k-1)1. D(n,1) = n
int dispo(int n, int k){if(k==1) return(n);else return(n*dispo(n-1, k-1));}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 16
Combinazioni
Combinazioni semplici di n oggetti distinti presi k a k: C(n,k) = D(n,k)/k!
int comb(int n, int k){ return(disp(n, k)/fat(k));}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 17
Combinazioni
Combinazioni semplici di n oggetti distinti presi k a k2. C(n,k) = n!/(k!(n-k)!)=[n*(n-1)!]/[k*(k-1)!(n-1-
(k-1))]== n/k * C(n-1,k-1) == n*C(n-1,k-1)/k1. C(n,1) = n
Un esercizio per voi!
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 18
La successione di Fibonacci
F(0) = 0F(1) = 1F(n) = F(n 1) + F(n 2)
Per esempioF(2) = 1 + 0 = 1F(3) = 1 + 1 = 2F(4) = 2 + 1 = 3F(5) = 3 + 2 = 5F(6) = 5 + 3 = 8F(7) = 8 + 5 = 13
Note storiche:Leonardo Fibonacci, 1170-1250, noto come Leonardo da Pisa, introdusse il sistema numerico arabo posizionale in Europa (Libro dell’abaco)
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 19
#include <stdio.h>long int fibo(int);
main(){int n; long int f;
printf("\nInserire n: \t");scanf("%d", &n);
f=fibo(n);printf(“Termine di posto %d = %ld\n", n, f);}
La successione di Fibonacci /1
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 20
long int fibo(int n) {if(n==0) return(0);else if(n==1) return(1); else return(fibo(n-1)+fibo(n-2));}
F(0) = 0
F(1) = 1
F(n) = F(n 1) + F(n -2)
La successione di Fibonacci /2
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 21
long int fibo(int n) {switch(n){ case 0: return(0);break; case 1: return(1);break; default: return(fibo(n-1)+fibo(n-2)); break;}
F(0) = 0
F(1) = 1
F(n) = F(n 1) + F(n -2)
La successione di Fibonacci /3
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 22
Altri problemi risolti ricorsivamente:
Contare le occorrenze di un carattere in una stringa
Ricerca lineare ricorsiva
Ordinamento per inserimento ricorsivo
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 23
Contare le occorrenze di un carattere in una stringa
int conta(char ch, char *str){ int ris;If(str[0]==‘\0’) ris=0;else if(ch==str[0]) ris=1+conta(ch,&str[1]); else ris=conta(ch,&str[1]);return (ris);}
O la stringa è vuota oppure essa contiene caratteri. In tal caso le occorrenze del carattere che interessa sono la somma delle occorrenze nella coda della stringa +1, se il primo elemento della stringa è proprio il carattere sotto osservazione.
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 24
Contare le occorrenze di un carattere in una stringa
include <stdio.h>#include <stdlib.h>int conta(char, char *);int main(){ int y=0; y = conta('c',"stcrincgca"); printf(" d = %d\n", y); system("PAUSE"); return 0;}int conta(char ch, char *stri){ int ris;if(stri[0]=='\0') ris=0;else if(ch==stri[0]) ris=1+conta(ch,&stri[1]); else ris=conta(ch,&stri[1]);return (ris); }
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 25
int appartiene(int a[], int dim, int elem){ if(a[dim-1]==elem) return TROVATO; else { dim=dim-1; if(dim>=1) appartiene(a,dim,elem); else return NON_TROVATO; } }
Ricerca lineare ricorsiva
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 26
Ordinamento per inserimento ricorsivo/1
Se l’array ha un solo elemento allora non fare nulla, perché l’array è ordinatoaltrimentiordina i primi n-1 elementi dell’array e quindi inserisci l’elemento di posto n, salvaguardando l’ordinamento
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 27
void ord(int a[], int dim){ int el; if (dim==1) return; else { el=a[dim-1]; dim=dim-1; ord(a,dim); inserisci(el,a,dim+1); }}
Ordinamento per inserimento ricorsivo/2
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 28
Complementi
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 29
Disposizioni
int dispo2(int k, int n){return(fat(n)/fat(n-k));}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 30
Moltiplicazione, potenza, somma, somma di quadrati /1
#include <stdlib.h>#include <stdio.h>#include <string.h>
#define DIM 5
int molt(int, int);long int potenza(int, int);long int somma(int [], int);long int sommaq(int [], int);
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 31
Moltiplicazione, potenza, somma, somma di quadrati /2
int main() { /* valido solo per m, n>0 */ int base, m=2, esp, n=3,p; long int pot; int a[DIM]={1,2,3,4,5};
p=molt(m,n); printf("%d x %d = %d\n",m,n,p);
printf("\n\n"); base=m; esp=n; pot=potenza(base,esp); printf("%d ELEVATO A %d = %d\n\n\n",m,n,pot);
printf("somma = %ld\n\n",somma(a,DIM)); printf("somma dei quadrati= %ld\n\n",sommaq(a,DIM));
system("PAUSE"); return 0;}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 32
Moltiplicazione, potenza, somma, somma di quadrati /3
int molt(int m, int n){ int prodotto; printf("dati di input: m=%d, n=%d\n",m,n);
if(n==1) prodotto=m; else prodotto=m+molt(m,n-1); printf("molt(%d, %d) = %d\n",m,n,prodotto); return prodotto;}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 33
Moltiplicazione, potenza, somma, somma di quadrati /4
long int potenza(int base, int esp){ int pot; printf("dati di input: base=%d, esp=%d\n",base,esp);
if(esp==0) pot=1; else pot=base*potenza(base,esp-1); printf("potenza(%d, %d) = %d\n",base,esp,pot); return pot;}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 34
Moltiplicazione, potenza, somma, somma di quadrati /5
long int sommaq(int a[], int dim){ if(dim==1) return a[dim-1]*a[dim-1]; else { return (sommaq(a,dim-1)+a[dim-1]*a[dim-1]); }}
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 35
Ricerca ricorsiva con indicazione della posizione
/* al momento della chiamata trovato=0 */
void appartiene(int a[], int dim, int elem, int *posiz, int *trovato){ if(a[dim-1]==elem) {*trovato=1; *posiz=dim-1;} else { dim=dim-1; if(dim>=1)appartiene(a,dim,elem,posiz,trovato); } }
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 36
Proposte di lavoro
1. Invertire un array di dati di tipo int2. Invertire una parola3. Ricercare un carattere in una stringa e
riportare la posizione4. Ricerca una parola in un array di
parole5. Calcolare l’intersezione tra due insiemi6. Calcolare l’unione tra due insiemi7. Calcolare il complemento di A in B