斐波那契数—递归方法的优化

6 篇文章 0 订阅
4 篇文章 0 订阅

现在说一下递归求解斐波那契数,直接模拟递推公式

递推公式

Fn=F(n-1)+F(n-2)(n>=2,n∈N*)

long long func(int n) {
	if (n == 1 || n == 2) {
		return 1;
	}
	return func(n - 1) + func(n - 2);
}

但是说一下使用递归求解的最常见问题:1、出现冗余程序分支 2、对于较大数据的计算会使用较多的堆栈内存 3、同样是处理较大数据时,可能会爆栈。

先说冗余分支,画了个图:

意思就是计算第五个斐波那契数需要先计算第3和第4个斐波那契数,但是计算第4个的时候又要计算第3个。但是由于处于不同的递归深度,递归函数不知道自己算过了,那么就出现了重复运算。而且恐怖的是:这种重复计算应该是一个指数增长的。

接下来说一下最常用的程序分支优化方法:

long long func_1(int n) {
	if (n == 1 || n == 2) {
		record[n] = 1;
		return record[n];
	}
	if (record[n])
		return record[n];
	else {
		record[n] = func_1(n - 1) + func_1(n - 2);
		return record[n];
	}

}

用一个额外的数组来存储已经计算过的值。

接下来我进行了一个测试,用运行时间来说明优化效果

#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <windows.h>
using namespace std;

vector<long long> record;
long long func(int n) {
	if (n == 1 || n == 2) {
		return 1;
	}
	return func(n - 1) + func(n - 2);
}
long long func_1(int n) {
	if (n == 1 || n == 2) {
		record[n] = 1;
		return record[n];
	}
	if (record[n])
		return record[n];
	else {
		record[n] = func_1(n - 1) + func_1(n - 2);
		return record[n];
	}

}
long long func_2(int n) {
	if (n == 1 || n == 2) {
		return 1;
	}
	long long pre_1, pre_2,current;
	pre_1 = 1;
	pre_2 = 1;
	for (int i = 3; i <= n;i++) {
		current = pre_1 + pre_2;
		pre_1 = pre_2;
		pre_2 = current;
	}

	return current;
}
int main() {
	int N=0;
	cout << "求第N位斐波那契数:N=";
	cin >> N;
	cout << endl;
	record.assign(N+1,0);

	DWORD start;
	start = GetTickCount();
	cout << func_2(N) << endl;
	cout << "迭代用时:" << (GetTickCount() - start) << endl;

	//start = GetTickCount();
	//cout<<func(N)<<endl;
	//cout << "直接递归的用时:" <<(GetTickCount() - start) << endl;

	start = GetTickCount();
	cout << func_1(N) << endl;
	cout << "优化重复运算的用时:"<<(GetTickCount() - start) << endl;

	system("pause");
	return 0;
}

测试结果:

虽然多计算了十个数,但是对于没有优化的递归,用时猛增。我在上面贴的代码中还实现了一下,使用常规的迭代方法,为了对比出递归方法的另外两个缺陷:

当我要求第5000位的时候,迭代方法还是使用了毫秒级的运算就得到了结果(其实long long型已经溢出,但是具体是什么数已经不是我关心的内容),但是递归直接把我的程序栈给用爆了,请看报的异常为“stack overflow”。

我把这篇,归为数学是有原因的,为什么很多搞计算机的人以前是搞数学的?请看:

求斐波那契数就尼玛一行程序,有解析解,根本不用模拟迭代过程。百度上还给我整什么方法二。。。方法还不止一个啊?凑!

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值