您的位置:首页 > 其它

算法导论-求(Fibonacci)斐波那契数列算法对比

2014-09-10 18:52 260 查看

目录

1、斐波那契数列(Fibonacci)介绍

2、朴素递归算法(Naive recursive algorithm)

3、朴素递归平方算法(Naive recursive squaring)

4 、自底向上算法(Bottom-up)

5、 递归平方算法(Recursive squaring)

6、完整代码(c++)

7、参考资料

内容

1、斐波那契数列(Fibonacci)介绍

Fibonacci数列应该也算是耳熟能详,它的递归定义如上图所示。

#ifndef FIBONACCI_HH
#define FIBONACCI_HH
struct Matrix2By2
{
Matrix2By2
(
unsigned long long m00 = 0,
unsigned long long m01 = 0,
unsigned long long m10 = 0,
unsigned long long m11 = 0
)
:m_00(m00), m_01(m01), m_10(m10), m_11(m11)
{
}

unsigned long long m_00;
unsigned long long m_01;
unsigned long long m_10;
unsigned long long m_11;
};
class Fibonacci
{
public:
unsigned long long Fibonacci_naive_reu(int n);//朴素递归算法
unsigned long long Fibonacci_bottom_up(int n);//自底向上算法
unsigned long long Fibonacci_recur_squar(int n);//递归平方算法
void MUL( unsigned long long MatrixA[2][2],unsigned long long MatrixB[2][2], unsigned long long MatrixResult[2][2] );
void  Matrix_power(int n,unsigned long long result[2][2]);

Matrix2By2 MatrixMultiply(const Matrix2By2& matrix1, const Matrix2By2& matrix2);
Matrix2By2 MatrixPower(unsigned int n);
unsigned long long Fibonacci_Solution3(unsigned int n);

};

unsigned long long Fibonacci::Fibonacci_naive_reu(int n)//朴素递归算法
{
int result[2] = {0,1};
if (n<2)       //退出条件
return result
;

return (Fibonacci_naive_reu(n-1)+ Fibonacci_naive_reu(n-2));//递归调用
}
/************************************************************************/
/*                         自底向上算法                                         */
//  时间复杂度T(n)=o(n)
/************************************************************************/
unsigned long long Fibonacci::Fibonacci_bottom_up(int n)//自底向上算法
{
int result[2] = {0, 1};
if(n < 2)
return result
;

unsigned long long  fibNMinusN_1 = 1;
unsigned long long  fibNMinusN_2 = 0;
unsigned long long  fibN = 0;
for(int i = 2; i <= n; ++ i)   //从底到上逐次计算出数列值
{
fibN = fibNMinusN_1 + fibNMinusN_2;

fibNMinusN_2 = fibNMinusN_1;
fibNMinusN_1 = fibN;
}

return fibN;//返回数组值
}
/************************************************************************/
/* 两个 矩阵相乘  、结果矩阵保存在 MatrixResult[2][2]中       */
/************************************************************************/
void Fibonacci::MUL( unsigned long long MatrixA[2][2],unsigned long long MatrixB[2][2], unsigned long long MatrixResult[2][2] )//矩阵相乘
{
for (int i=0;i<2 ;i++)
{
for (int j=0;j<2 ;j++)
{
MatrixResult[i][j]=0;
for (int k=0;k<2 ;k++)
{
MatrixResult[i][j]=MatrixResult[i][j]+MatrixA[i][k]*MatrixB[k][j];
}
}
}
}
/************************************************************************/
/*  下面矩阵的n次幂,结果保存在      Result[2][2]                   */
//   矩阵的n次幂,采用分治法,与x的n 次方算法一致,时间复杂度T(n)=o(logn)
//    1    1
//    1    0
/************************************************************************/
void Fibonacci::Matrix_power(int n,unsigned long long Result[2][2])//求矩阵幂
{
unsigned long long AResult[2][2];
unsigned long long zResult1[2][2];
unsigned long long zResult2[2][2];

AResult[0][0]=1;AResult[0][1]=1;AResult[1][0]=1;AResult[1][1]=0;
if (1==n)
{
Result[0][0]=1;Result[0][1]=1;Result[1][0]=1;Result[1][1]=0;
}
else if (n%2==0)
{
Matrix_power(n/2,zResult1);
MUL(zResult1,zResult1,Result);
}
else if (n%2 == 1)
{
Matrix_power((n-1)/2,zResult1);
MUL(zResult1,zResult1,zResult2);
MUL(zResult2,AResult,Result);
}
}
unsigned long long Fibonacci::Fibonacci_recur_squar(int n)//递归平方算法
{
unsigned long long fib_result[2][2];
int result[2] = {0, 1};
if(n < 2)
return result
;
Matrix_power(n,fib_result);
return fib_result[0][1];
}

/************************************************************************/
/*     下面是网上copy的递归平方算法的代码                          */
/************************************************************************/
///////////////////////////////////////////////////////////////////////
// Multiply two matrices
// Input: matrix1 - the first matrix
//        matrix2 - the second matrix
//Output: the production of two matrices
///////////////////////////////////////////////////////////////////////
Matrix2By2 Fibonacci::MatrixMultiply
(
const Matrix2By2& matrix1,
const Matrix2By2& matrix2
)
{
return Matrix2By2(
matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);
}

///////////////////////////////////////////////////////////////////////
// The nth power of matrix
// 1  1
// 1  0
///////////////////////////////////////////////////////////////////////
Matrix2By2 Fibonacci::MatrixPower(unsigned int n)
{
Matrix2By2 matrix;
if(n == 1)
{
matrix = Matrix2By2(1, 1, 1, 0);
}
else if(n % 2 == 0)
{
matrix = MatrixPower(n / 2);
matrix = MatrixMultiply(matrix, matrix);
}
else if(n % 2 == 1)
{
matrix = MatrixPower((n - 1) / 2);
matrix = MatrixMultiply(matrix, matrix);
matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
}

return matrix;
}
///////////////////////////////////////////////////////////////////////
// Calculate the nth item of Fibonacci Series using devide and conquer
///////////////////////////////////////////////////////////////////////
unsigned long long Fibonacci::Fibonacci_Solution3(unsigned int n)
{
int result[2] = {0, 1};
if(n < 2)
return result
;

Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
return PowerNMinus2.m_00;
}
#endif


Fibonacci.h

Fibonacci.cpp (主函数)

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
#include "Fibonacci.h"

int main()
{
Fibonacci fib;
clock_t startTime_For_Fibonacci_naive_reu ;
clock_t endTime_For_Fibonacci_naive_reu ;
clock_t startTime_For_Fibonacci_bottom_up ;
clock_t endTime_For_Fibonacci_bottom_up ;
clock_t startTime_For_Fibonacci_recur_squar1 ;
clock_t endTime_For_Fibonacci_recur_squar1 ;
clock_t startTime_For_Fibonacci_recur_squar2 ;
clock_t endTime_For_Fibonacci_recur_squar2 ;

startTime_For_Fibonacci_naive_reu=clock();
cout<<fib.Fibonacci_naive_reu(40)<<endl;//朴素递归算法
endTime_For_Fibonacci_naive_reu=clock();

startTime_For_Fibonacci_bottom_up=clock();
cout<<fib.Fibonacci_bottom_up(40)<<endl;//自底向上算法
endTime_For_Fibonacci_bottom_up=clock();

startTime_For_Fibonacci_recur_squar1=clock();
cout<<fib.Fibonacci_recur_squar(40)<<endl;//我自己编写的递归平方算法
endTime_For_Fibonacci_recur_squar1=clock();

startTime_For_Fibonacci_recur_squar2=clock();
cout<<fib.Fibonacci_Solution3(40)<<endl;//网上copy的递归平方算法
endTime_For_Fibonacci_recur_squar2=clock();

cout<<"朴素递归算法用时: "<<(endTime_For_Fibonacci_naive_reu-startTime_For_Fibonacci_naive_reu)/(1.0*CLOCKS_PER_SEC)<<"秒"<<endl;
cout<<"自底向上算法用时: "<<(endTime_For_Fibonacci_bottom_up-startTime_For_Fibonacci_bottom_up)/(1.0*CLOCKS_PER_SEC)<<"秒"<<endl;
cout<<"我自己编写的递归平方算法用时: "<<(endTime_For_Fibonacci_recur_squar1-startTime_For_Fibonacci_recur_squar1)/(1.0*CLOCKS_PER_SEC)<<"秒"<<endl;
cout<<"网上copy的递归平方算法用时: "<<(endTime_For_Fibonacci_recur_squar2-startTime_For_Fibonacci_recur_squar2)/(1.0*CLOCKS_PER_SEC)<<"秒"<<endl;
system("Pause");
return 0;
}


输出:



结:朴素递归算法用时太多,实用价值不大,自底向上算法效率为线性,较高,平时用较多,递归平方算法效率为对数级,且编程可实现,实用价值很大。并且经过测试,当n值变很大后,递归平方算法效率明显高于自底向上算法效率。

7、参考资料

【1】http://zhedahht.blog.163.com/blog/static/25411174200722991933440/

【2】http://blog.csdn.net/xyd0512/article/details/8220506
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: