30.05.2013 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!