Appunti per il modulo di algoritmi e strutture dati - Sezione di ...
Appunti per il modulo di algoritmi e strutture dati - Sezione di ...
Appunti per il modulo di algoritmi e strutture dati - Sezione di ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
• Base. n = 0. In questo caso abbiamo fatt(0) = 1 = 0!.<br />
• Induzione.<br />
Ipotesi: fatt(n)=n!.<br />
Tesi: fatt(n+1)=(n+1)!<br />
Dim.<br />
fatt(n + 1) = (n + 1) ∗ fatt(n + 1 − 1) <strong>per</strong> definizione <strong>di</strong> fatt e poiché (n + 1) > 0<br />
= (n + 1) ∗ fatt(n)<br />
= (n + 1) ∗ n! <strong>per</strong> ipotesi induttiva<br />
= (n + 1)! <strong>per</strong> definizione <strong>di</strong> fattoriale.<br />
La programmazione ricorsiva ha un’applicazione naturale nella manipolazione <strong>di</strong> tipi <strong>di</strong> dato definiti<br />
ricorsivamente. Un esempio <strong>di</strong> tale tipo tipo è la lista <strong>di</strong> elementi, che può essere definita come segue:<br />
• la lista vuota è una lista;<br />
• un elemento seguito da una lista è una lista.<br />
Una buona metodologia <strong>per</strong> scrivere funzioni che lavorano su liste è quella <strong>di</strong> ricalcare la definizione<br />
<strong>di</strong> lista, cioè considerare come caso base la lista vuota e come caso ricorsivo <strong>il</strong> caso <strong>di</strong> un elemento seguito<br />
da una lista. Per esempio, se la lista è rappresentata con elementi della struttura:<br />
struct Elem {<br />
int inf ;<br />
Elem * next ;<br />
};<br />
e la lista vuota è rappresentata con NULL, le funzioni seguenti sono definite con la metodologia suddetta:<br />
la prima calcola la lunghezza <strong>di</strong> una lista, la seconda <strong>il</strong> numero <strong>di</strong> volte che un elemento compare in una<br />
lista (<strong>il</strong> test (p == NULL) può essere sostituito da (!p).<br />
int length ( Elem * p) {<br />
if (p == NULL ) return 0;<br />
return 1+ length (p-> next );<br />
}<br />
int howMany ( Elem * p, int x) {<br />
if (p == NULL ) return 0;<br />
return (p-> inf == x)+ howMany (p->next , x);<br />
}<br />
Naturalmente non sempre i casi non ricorsivi <strong>di</strong> una funzione che o<strong>per</strong>a su liste coincidono esattamente<br />
con <strong>il</strong> caso della lista vuota, ma ci possono essere degli altri argomenti su cui la funzione dà imme<strong>di</strong>atemente<br />
<strong>il</strong> risultato. In genere i casi non ricorsivi sono un soprainsieme dei casi base del tipo <strong>di</strong> dato. Nella<br />
seguente funzione che cerca se un elemento compare nella lista, i casi non ricorsivi sono due: lista vuota<br />
e lista <strong>il</strong> cui primo elemento è quello cercato.<br />
int belongs ( Elem * l, int x) {<br />
if (l == NULL ) return 0;<br />
if (l-> inf == x) return 1;<br />
return belongs (l->next , x);<br />
}<br />
14