算法设计与分析(第三周)递归/迭代求Fibonacci前n项 【以及递归算法速度慢的原因】

为了理解递归写的。真想求Fibonacci前n项,迭代是更好的选择,简单并且速度快。另外,注意一下溢出问题。

递归算法速度慢的原因

递归调用本身需要使用系统栈,每次分配函数内存以及栈都需要时间.不过这个过程耗时并不多,可以说,单纯的递归本身并不比非递归慢多少.
然而,实践中就会发现,递归处理部分问题,特别是递推类问题时会表现出效率极低.这个问题的出现是因为重复计算.
举例说,用递归求解斐波那契数列的第n项,一般的递归公式为

f(n) = f(n-1)+f(n-2)
f(2) = 1
f(1) = 1

请尝试模拟计算机运行这个递归,你会发现,其中的某一项f(x)并不是只算了一次. 当你计算f(5)的时候,你会试图计算f(4)和f(3),然而在你计算f(4)的时候其实也要计算f(3),这样f(3)就被调用了两次.
计算Fibonacci(5)为例:
在这里插入图片描述
从上图可以看出,在计算Fib(5)的过程中,Fib(1)计算了两次、Fib(2)计算了3次,Fib(3)计算了两次,本来只需要5次计算就可以完成的任务却计算了9次。这个问题随着规模的增加会愈发凸显,以至于Fib(1000)已经无法再可接受的时间内算出。
想象这个过程是指数型扩展的,效率会随着n的增大极快地下降.
要解决这个问题,可以使用记忆化思想.
定义记忆数组r,函数体改为:

define f(n):
if r[n] is defined, then simply return r[n] as the answer.
else, f(n) = f(n-1) + f(n-2)
before return the value, take it down in r[n].

如此改进之后的递归函数效率上与递推算法相差无几.

递归代码

到后面计算速度巨慢

运行效果

计算斐波那契数列的前多少项?(输入过大可能溢出)
30
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 请按任意键继续. . .

//输入一个数num,打印斐波那契数列的前num项
#include<iostream>
using namespace std;
int fib(int num)//n是当前项的值,num是当前项数
{
	if (num<=1)return 1;
	else return  fib(num - 1) + fib(num - 2);
}
int main()
{
	//输入
	int num;
	cout << "计算斐波那契数列的前多少项?(输入过大可能溢出)\n";
	cin >> num;

	//计算并输出
	int i;
	for (i = 0; i < num; i++)
	{
		cout << fib(i) << ' ';
	}
	
	system("pause");
}

迭代代码

几乎瞬间计算出来

运行效果

计算前多少项?
50
2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 4807526976 7778742049 12586269025 请按任意键继续. . .

//打印斐波那契前n项
#include<iostream>
using namespace std;
int main()
{
	//输入
	int num;
	cout << "计算前多少项?\n";
	cin >> num;

	//计算
	long long int a[50] = { 1,1 };
	int i;
	for (i = 2; i < num; i++)
	{
		a[i] = a[i - 1] + a[i - 2];
		cout << a[i] << ' ';
	}

	system("pause");
}

猜你喜欢

转载自blog.csdn.net/sinat_42483341/article/details/88104232