150 likes | 351 Views
Ricorsione. Strumento potente per definizioni matematiche Possibilità di definire insieme infinito di oggetti con regola finita possibilità di descrivere un insieme infinito di computazioni con un programma finito. Ricorsione in matematica.
E N D
Ricorsione • Strumento potente per definizioni matematiche • Possibilità di definire insieme infinito di oggetti con regola finita • possibilità di descrivere un insieme infinito di computazioni con un programma finito
Ricorsione in matematica • Le formule matematiche sono spesso espresse in termini ricorsivi • Esempio: definizione di fattoriale 1!=1 N!=N * (N-1)!
Metodi ricorsivi • Contengono riferimenti espliciti a sé stessi • direttamente ricorsivi • Un metodo ne invoca un altro e l’esecuzione di quest’ultimo porta ad un certo punto ad invocare nuovamente (direttamente o indirettamente) il metodo originale • indirettamente ricorsivi
Ricorsione infinita • Requisito fondamentale: • chiamata ricorsiva subordinata ad una condizione che ad un certo istante deve divenire non soddisfatta • Qualsiasi definizione ricorsiva deve avere una parte non ricorsiva, detta base della ricorsione, che permette alla ricorsione stessa di terminare • Nell’esempio precedente del fattoriale la base è 1! che è posto uguale ad 1
Variabili in metodi ricorsivi • Ogni invocazione genera un nuovo insieme di variabili locali • Ogni parametro riceve un valore iniziale in base alla nuova invocazione • Ogni volta che il metodo termina si ritorna al metodo che lo ha chiamato ( che potrebbe essere lo stesso)
Numeri di Fibonacci • Schema più complicato di composizione ricorsiva che potrebbe (e dovrebbe) essere tradotto in forma iterativa • Definizione: • fib0 = 0 • fib1 = 1 • fibn+1 = fibn + fibn-1
Implementazione ricorsiva int computeFib(int n) { if (n == 0) return 0; if (n == 1) return 1; return computeFib(n-1)+computeFib(n-2); }
5 4 3 2 3 1 2 2 1 0 1 1 0 1 0 Numero di invocazioni • Numero totale di invocazioni cresce esponenzialmente
Implementazione iterativa int computeFib(int n) { int i = 1, x = 1, y = 0; while (i < n) { i = i+1; x = x+ y; y = x -y; } return x; }
Considerazioni • Ricorsione deve essere evitata se esiste una soluzione iterativa ovvia • Non vuol dire evitare la ricorsione a qualunque costo • esistono molte buone applicazioni della ricorsione • algoritmi per loro natura ricorsivi vanno implementati con metodi ricorsivi
Le torri di Hanoiinventato nel 1880 da Lucas • Tre aste (o torri) ed n dischi di dimensioni diverse (con buco per inserirli nelle aste) • All’inizio tutti i dischi sono nell’asta 1 • in ordine decrescente di grandezza • Obiettivo: portarli nella torre 3 rispettando le regole seguenti • nessun disco mai sopra uno più piccolo • si può spostare un solo disco alla volta • dischi sempre collocati su una torre (non a parte) • solo disco in cima ad una torre può essere spostato
Algoritmo ricorsivo • Obiettivo: spostare k dischi da torre 1 a torre 3 • Algoritmo: • Spostare k-1 dischi da torre originalea torre temporanea • Spostare 1 disco da torre originale a torre di destinazione • Spostare k-1 dischi da torre temporanea a torre di destinazione
Implementazione 1 void moveTowers(int k, int o,int d) { if (k > 0) { moveTowers(k-1, o, 6-o-d); System.out.println("Sposta da "+o+"a"+d); moveTowers(k-1,6-o-d,d); } }