LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di...

36
LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 1 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10

Transcript of LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di...

Page 1: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 1

Linguaggi di programmazione ILa ricorsione

Prof. Luigi Di Lascio

Lezione 10

Page 2: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La 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

Page 3: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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)!

Page 4: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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)

Page 5: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 5

Il proccesso ricorsivo

Page 6: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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 . . .

Page 7: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 8: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 9: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 10: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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]

Page 11: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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]); }

Page 12: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 13: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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;}

Page 14: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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)!)

Page 15: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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));}

Page 16: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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));}

Page 17: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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!

Page 18: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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)

Page 19: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 20: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 21: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 22: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 23: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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.

Page 24: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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); }

Page 25: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 26: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 27: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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

Page 28: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 28

 

 

 

 

 

 

Complementi

Page 29: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

LdL - LP1 - ver. 6 - lez. 10 - aa 05-06 29

Disposizioni

 

 

 

 

 

 

int dispo2(int k, int n){return(fat(n)/fat(n-k));}

Page 30: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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);

Page 31: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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;}

Page 32: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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;}

Page 33: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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;}

Page 34: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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]); }}

Page 35: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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); } }

Page 36: LdL - LP1 - ver. 6 - lez. 10 - aa 05-061 Linguaggi di programmazione I La ricorsione Prof. Luigi Di Lascio Lezione 10.

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