La Ricorsione

di il
6 risposte

La Ricorsione

Salve,
ragazze/i ho un problema, non capisco la ricorsione.
E' ormai da 3 mesi che ci combatto e non riesco a capirla davvero a fondo.
conosco ormai tutti i siti (universitari e non) dove spiegano la ricorsione. Ma non riesco ad assimilarne il concetto.
Sto studiando col libro di Deitel e sono andato avanti fino ad arrivare al passaggio dei vettori alle funzioni, ma resto sempre con questo buco che non riesco a riempire.
Neppure il fattoriale capisco come funziona...figuriamoci Fibonacci.
Non è che qualcuno potrebbe spiegarmelo passo per passo in base a questo codice?

#include <stdio.h>
#include <stdlib.h>

long factorial( long number );      

main()                                               
{

int i;                                                                
                        
for (i = 0; i <= 10; i++)                                  
printf("%2d! = %ld\n", i, factorial(i));          
                                                                                                                                                                                                         
return 0;
                                                                        
}                                                                       
long factorial( long number ) 
{                                                                         
    if (number <= 1)
    return 1;
    else
    return (number * factorial(number - 1));
}
Principalmente non capisco una cosa...
quando il compilatore legge la riga
return (number * factorial(number - 1)); 
dovrebbe richiamare di nuovo la funzione e decrementare il numero.
Ma quando "number" arriva ad uno e il compilatore va a rileggere la funzione da capo non dovrebbe
ritornare 1 basandosi su questa riga ?
    if (number <= 1)
    return 1;
e quindi la funzione dovrebbe ritornare sempre "1".
O mi sbaglio ?

6 Risposte

  • Re: La Ricorsione

    Quando chiami una funzione i valori della funzione chiamante sono salvati in una zona di memoria apposita (stack memory), la funzione chiamata lavora su un' altra zona di memoria.
    Questo anche nel caso che si chiami la stessa funzione (ricorsione), i valori delle variabili sono duplicati in aree di memoria differenti.

    Quindi nel caso del fattoriale di 10 esisteranno una decina di contesti (uno per ogni funzione chiamata) in cui i valori della variabile 'number' avranno valori differenti.

    Quando arrivi a 'number==1', hai alle spalle 10 chiamate di funzione in cui nel loro stack c'è scritto 'number == 2', 'number==3' ecc. man mano che ritorni questi stack vengono ripristinati e le funzioni eseguite coi loro valori.

    Dubito di essere stato chiaro, ma ci ho provato .
  • Re: La Ricorsione

    
    factorial(i)
    
    carta e penna e segui:
    prendiamo per esempio i = 5.
    1. prima chiamata (return 5 * factorial(5-1))
    2. seconda chiamata (return 4 * factorial(4-1))
    3. terza chiamata (return 3 * (factorial(3 -1))
    4. quarta chiamata (return 2 * factorial(2-1))
    5. quinta chiamata (return 1)
    6. torno al punto 4 perche esco dalla funzione del punto 5 e ritorno (2 * 1)
    7. torno al punto 3 perche esco dalla funzione del punto 4 e ritorno (3 * 2 * 1)
    8. torno al punto 2 perche esco dalla funzione del punto 3 e ritorno (4 * 3 * 2 * 1)
    9. torno al punto 1 perche esco dalla funzione del punto 2 e ritorno (5 * 4 * 3 * 2 * 1)
    10. ritorno dalla funzione col valore del prodotto dei numeri e cioè 120.
  • Re: La Ricorsione

    Ma questa "Ricorsione" è davvero così importante ? Che potrebbe succedere se salto l'argomento ?
    Ho letto da qualche parte che non serve a molto e si usa molto raramente.

    Comunque grazie mille per l'aiuto, lo analizzerò con calma e cura.
  • Re: La Ricorsione

    È vero, puoi trascorrere una vita lunga e felice senza mai usare la ricorsione.
    Comunque insisti, vedrai che quando arriverà l' illuminazione ti sembrerà tutto semplice e ovvio.
  • Re: La Ricorsione

    Natura ha scritto:


    Salve,
    Ma quando "number" arriva ad uno e il compilatore va a rileggere la funzione da capo non dovrebbe
    ritornare 1 basandosi su questa riga ?
        if (number <= 1)
        return 1;
    e quindi la funzione dovrebbe ritornare sempre "1".
    O mi sbaglio ?
    Ciao Natura
    Riprovo con una spiegazione più sintetica:

    Se una funzione usa le variabili a, b, c e richiama un' altra funzione, l' altra funzione NON altera a, b, c, neppure se al suo interno usa delle variabili che hanno lo stesso nome.

    Ebbene lo stesso capita con la ricorsione. Anche se la funzione chiamata ha lo stesso nome lavora su variabili differenti.
  • Re: La Ricorsione

    Prova a considerare la funzione fattoriale scritta cosi:
    
    long factorial( long number ) 
    {  
        long result;    
        long n = number;
                                                                          
        if (n <= 1)
            result = 1;
        else
            result = n * factorial(n - 1);
    
        return result;
    }
    
    Dovrebbe risultare più chiaro il valore assunto dalle variabili.
Devi accedere o registrarti per scrivere nel forum
6 risposte