使用Memoization,以避免遞歸重復計算
考慮Fibonacci(斐波那契)問題;
Fibonacci問題是可以通過簡單的遞歸方法來解決:
int fib ( n )
{
if ( n == 0 || n == 1 ) {
return 1;
}
else {
return fib( n - 2 ) + fib ( n - 1 );
}
}
{
if ( n == 0 || n == 1 ) {
return 1;
}
else {
return fib( n - 2 ) + fib ( n - 1 );
}
}
注:在這里,我們考慮Fibonacci 系列從1開始,因此,該系列看起來:1,1,2,3,5,8,...
注意:從遞歸樹,我們計算fib(3)函數2次,fib(2)函數3次。這是相同函數的重復計算。如果n非常大,fib
這個簡單的技術叫做Memoization,可以被用在遞歸,加強計算速度。
fibonacci 函數Memoization的代碼,應該是下面的這個樣子:
int calc_fib (
int n )
{
int val[ n ] , i;
for ( i = 0; i <=n; i++ ) {
val[ i ] = - 1; // Value of the first n + 1 terms of the fibonacci terms set to -1
}
val[ 0 ] = 1; // Value of fib ( 0 ) is set to 1
val[ 1 ] = 1; // Value of fib ( 1 ) is set to 1
return fib( n , val );
}
int fib( int n , int* value )
{
if ( value[ n ] != - 1 ) {
return value[ n ]; // Using memoization
}
else {
value[ n ] = fib( n - 2 , value ) + fib ( n - 1 , value ); // Computing the fibonacci term
}
return value[ n ]; // Returning the value
}
{
int val[ n ] , i;
for ( i = 0; i <=n; i++ ) {
val[ i ] = - 1; // Value of the first n + 1 terms of the fibonacci terms set to -1
}
val[ 0 ] = 1; // Value of fib ( 0 ) is set to 1
val[ 1 ] = 1; // Value of fib ( 1 ) is set to 1
return fib( n , val );
}
int fib( int n , int* value )
{
if ( value[ n ] != - 1 ) {
return value[ n ]; // Using memoization
}
else {
value[ n ] = fib( n - 2 , value ) + fib ( n - 1 , value ); // Computing the fibonacci term
}
return value[ n ]; // Returning the value
}
上面代碼的紅色部分,不知道為什么可以那么聲明,在標准C和C++中數組都不可以那樣聲明吧,可能是使用編譯器進行了擴展。
下面是我用C++寫的:
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int fib( int n, int val[])
{
if(val[n]!=- 1)
return val[n];
else
{
val[n]=fib(n- 1,val)+fib(n- 2,val);
return val[n];
}
}
void cal_fib( int n)
{
int *val= new int[n+ 1];
for( int i= 0;i<=n;i++)
val[i]=- 1;
val[ 0]= 0;
val[ 1]= 1;
fib(n,val);
copy(val,val+n+ 1,ostream_iterator< int>(cout, " "));
cout<<endl;
delete[] val;
}
int main()
{
for( int i= 3;i<= 15;i++)
cal_fib(i);
}
#include <algorithm>
#include <iterator>
using namespace std;
int fib( int n, int val[])
{
if(val[n]!=- 1)
return val[n];
else
{
val[n]=fib(n- 1,val)+fib(n- 2,val);
return val[n];
}
}
void cal_fib( int n)
{
int *val= new int[n+ 1];
for( int i= 0;i<=n;i++)
val[i]=- 1;
val[ 0]= 0;
val[ 1]= 1;
fib(n,val);
copy(val,val+n+ 1,ostream_iterator< int>(cout, " "));
cout<<endl;
delete[] val;
}
int main()
{
for( int i= 3;i<= 15;i++)
cal_fib(i);
}
輸出的結果如下:
參考:http://blog.jobbole.com/1198/
