2009-10-05 16 views
35

Sto avendo difficoltà a capire il motivo per cuiricorsivo Fibonacci

#include <iostream> 

using namespace std; 

int fib(int x) { 
    if (x == 1) { 
     return 1; 
    } else { 
     return fib(x-1)+fib(x-2); 
    } 
} 

int main() { 
    cout << fib(5) << endl; 
} 

risultati in un errore di segmentazione. Una volta che x scende a 1 non dovrebbe eventualmente tornare?

+13

La complessità temporale di questo algoritmo è O (2^n). È molto cattivo. Per esempio, il calcolo di f (30) richiede circa 1 miliardo di operazioni. Usa la programmazione dinamica nel tuo caso. –

+5

@Alexey, sono sicuro che l'OP vuole solo imparare. Se le prestazioni sono un problema, la meta-programmazione è davvero la strada da percorrere. – LiraNuna

+2

@Alexey Malistov: No, usa invece l'approccio iterativo. – Gumbo

risposta

146

Quando x==2 si chiama fib(1) e fib(0):

return fib(2-1)+fib(2-2); 

Considerate che avverrà fib(0) viene valutata ...

+70

+1 per non dare direttamente la risposta ma indicare dove si trova il problema. Molto meglio per qualcuno che sta imparando. – Xetius

+4

+1, uso la stessa tecnica con il mio bambino più grande (9) e stimola la sua capacità di risolvere i problemi. –

38

Il motivo è perché successione di Fibonacci inizia con due entità conosciute, 0 e 1. Il tuo codice controlla solo uno di essi (essendo uno).

modificare il codice per

int fib(int x) { 
    if (x == 0) 
     return 0; 

    if (x == 1) 
     return 1; 

    return fib(x-1)+fib(x-2); 
} 

per includere sia 0 e 1.

+3

La serie non inizia da 1,1? – vpram86

+1

Questo non è quello che mi è stato insegnato, e non quello che suggerisce Wikipedia - http://en.wikipedia.org/wiki/Fibonacci_number – LiraNuna

+2

@Aviatore: dipende da come si definiscono i numeri di Fibonacci. ;) – Spoike

11

Perché non usare algoritmo iterativo?

int fib(int n) 
{ 
    int a = 1, b = 1; 
    for (int i = 3; i <= n; i++) { 
     int c = a + b; 
     a = b; 
     b = c; 
    }   
    return b; 
} 
+3

Questo è l'approccio migliore. Ma ha chiesto una soluzione ricorsiva. – Gumbo

+0

@ Gumbo, l'approccio "migliore" sarebbe la meta-programmazione, senza dubbio. – LiraNuna

+0

@LiraNuna: Questa non è meta-programmazione. – Gumbo

4

Penso che questa soluzione è breve e sembra sembra piacevole:

long long fib(int n){ 
    return n<=2?1:fib(n-1)+fib(n-2); 
} 

Edit: come jweyrich accennato, vera funzione ricorsiva dovrebbe essere:

long long fib(int n){ 
     return n<2?n:fib(n-1)+fib(n-2); 
    } 

(perché fib (0) = 0. ma base su formula ricorsiva, fib (0) sarà 1)

Per comprendere l'algoritmo di ricorsione, si dovrebbe attingere al tuo giornale e la cosa più importante è: "Pensa normale come spesso".

+1

'' fib (0) 'ha un risultato errato in 1. Ciò risolverebbe:' return x <2? x: fibonnaci (x-1) + fibonnaci (x-2); '. Qui una condizione extra esclusivamente per 'fib (2)' rallenterebbe la funzione. – jweyrich

+0

spesso la funzione fibonnaci n esegue solo fino a circa 50 con chiamata ricorsiva. Non credo che le condizioni aggiuntive possano rallentare la chiamata ricorsiva – hqt

+1

Il mio punto era che la funzione 'fib' restituisce il risultato errato per' fib (0) '. Per favore, ignora il resto :-) – jweyrich

3
int fib(int n) { 
    if (n == 1 || n == 2) { 
     return 1; 
    } else { 
     return fib(n - 1) + fib(n - 2); 
    } 
} 

nella sequenza di Fibonacci primi 2 numeri sequel sempre a 1, quindi ogni volta che il valore è diventato 1 o 2 deve restituire 1

2
int fib(int x) 
{ 
    if (x == 0) 
     return 0; 
    else if (x == 1 || x == 2) 
     return 1; 
    else 
     return (fib(x - 1) + fib(x - 2)); 
} 
+0

Hai una risposta alla domanda (vedi * perché * sotto) anche tu? – Trinimon

+2

if (x <3) return (int) ((bool) x); potrebbe funzionare anche –

1
int fib(int x) 
{ 
    if (x < 2) 
     return x; 
    else 
     return (fib(x - 1) + fib(x - 2)); 
} 
+0

Perfetto!Ho appena rimosso il resto. – Avelino

1
if(n==1 || n==0){ 
    return n; 
}else{  
    return fib(n-1) + fib(n-2); 
} 

Tuttavia, utilizzando la ricorsione per ottenere Fibonacci il numero è una cattiva pratica, perché la funzione è chiamata circa 8,5 volte rispetto al numero ricevuto. E.g. per ottenere il numero di fibonacci di 30 (1346269) - la funzione è chiamata 7049122 volte!

7

Per definizione, i primi due numeri nella sequenza di Fibonacci sono 1 e 1 oppure 0 e 1. Pertanto, è necessario gestirlo.

#include <iostream> 
using namespace std; 

int Fibonacci(int); 

int main(void) { 
    int number; 

    cout << "Please enter a positive integer: "; 
    cin >> number; 
    if (number < 0) 
     cout << "That is not a positive integer.\n"; 
    else 
     cout << number << " Fibonacci is: " << Fibonacci(number) << endl; 
} 

int Fibonacci(int x) 
{ 
    if (x < 2){ 
    return x; 
    }  
    return (Fibonacci (x - 1) + Fibonacci (x - 2)); 
} 
3

Questa è la mia soluzione a Fibonacci problema con la ricorsione.

#include <iostream> 
using namespace std; 

int fibonacci(int n){ 
    if(n<=0) 
     return 0; 
    else if(n==1 || n==2) 
     return 1; 
    else 
     return (fibonacci(n-1)+fibonacci(n-2)); 
} 

int main() { 
    cout << fibonacci(8); 
    return 0; 
} 
0

La mia soluzione è:

#include <iostream> 


    int fib(int number); 

    void call_fib(void); 

    int main() 
    { 
    call_fib(); 
    return 0; 
    } 

    void call_fib(void) 
    { 
     int input; 
     std::cout<<"enter a number\t"; 
     std::cin>> input; 
     if (input <0) 
     { 
     input=0; 
     std::cout<<"that is not a valid input\n" ; 
     call_fib(); 
    } 
    else 
    { 
     std::cout<<"the "<<input <<"th fibonacci number is "<<fib(input); 
    } 

    } 





    int fib(int x) 
    { 
    if (x==0){return 0;} 
    else if (x==2 || x==1) 
    { 
     return 1; 
    } 

    else if (x>0) 
    { 
     return fib(x-1)+fib(x-2); 
    } 
    else 
    return -1; 
    } 

restituisce fib (0) = 0 e di errore se negitive

+0

Questo in realtà non risponde alla domanda ... –

0

penso che sia la migliore soluzione di Fibonacci utilizzando la ricorsione.

#include<bits/stdc++.h> 
typedef unsigned long long ull; 
typedef long long ll; 
ull FIBO[100005]; 
using namespace std; 
ull fibo(ull n) 
{ 
    if(n==1||n==0) 
     return n; 
    if(FIBO[n]!=0) 
     return FIBO[n]; 
    FIBO[n] = (fibo(n-1)+fibo(n-2)); 
    return FIBO[n]; 
} 
int main() 
{ 
    for(long long i =34;i<=60;i++) 
     cout<<fibo(i)<<" " ; 
    return 0; 
}