递归思想:
递归就是有去(递去)有回(归来)。“有去”是指:递归问题必须可以分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决,就像钥匙可以打开所有门上的锁一样;“有回”是指 : 这些问题的演化过程是一个从大到小,由近及远的过程,并且会有一个明确的终点(临界点),一旦到达了这个临界点,就不用再往更小、更远的地方走下去。最后,从这个临界点开始,原路返回到原点,原问题解决。
原文链接:https://blog.csdn.net/yufanhui/article/details/80939847
递归定义:
在高级语言中,函数调用自己和调用其他函数没有本质的不同,我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称为递归函数。
递归的三大要素
第一要素:明确你这个函数想要干什么
对于递归,我觉得很重要的一个事就是,这个函数的功能是什么,他要完成什么样的一件事,而这个,是完全由你自己来定义的。也就是说,我们先不管函数里面的代码什么,而是要先明白,你这个函数是要用来干什么。
例如,我定义了一个函数:
// 算 n 的阶乘(假设n不为0)
int f(int n){
}
这个函数的功能是算 n 的阶乘。好了,我们已经定义了一个函数,并且定义了它的功能是什么,接下来我们看第二要素。
第二要素:寻找递归结束条件
所谓递归,就是会在函数内部代码中,调用这个函数本身,所以,我们必须要找出递归的结束条件,不然的话,会一直调用自己,进入无底洞。也就是说,我们需要找出当参数为啥时,递归结束,之后直接把结果返回,请注意,这个时候我们必须能根据这个参数的值,能够直接知道函数的结果是什么。
原文链接:https://blog.csdn.net/dreamispossible/article/details/90552557
例如,上面那个例子,当 n = 1 时,那你应该能够直接知道 f(n) 是啥吧?此时,f(1) = 1。完善我们函数内部的代码,把第二要素加进代码里面,如下:
// 算 n 的阶乘(假设n不为0)
int f(int n){
if(n == 1){
return 1;
}
}
有人可能会说,当 n = 2 时,那我们可以直接知道 f(n) 等于多少啊,那我可以把 n = 2 作为递归的结束条件吗?
当然可以,只要你觉得参数是什么时,你能够直接知道函数的结果,那么你就可以把这个参数作为结束的条件,所以下面这段代码也是可以的。
// 算 n 的阶乘(假设n>=2)
int f(int n){
if(n == 2){
return 2;
}
}
第三要素:找出函数的等价关系式
第三要素就是,我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变。
例如,f(n) 这个范围比较大,我们可以让 f(n) = n * f(n-1)。这样,范围就由 n 变成了 n-1 了,范围变小了,并且为了原函数f(n) 不变,我们需要让 f(n-1) 乘以 n。
说白了,就是要找到原函数的一个等价关系式,f(n) 的等价关系式为 n * f(n-1),即
f(n) = n * f(n-1)。
找出了这个等价,继续完善我们的代码,我们把这个等价式写进函数里。如下:
// 算 n 的阶乘(假设n不为0)
int f(int n){
if(n <= 2){
return n;
}
// 把 f(n) 的等价操作写进去
return f(n-1) * n;
}
至此,递归三要素已经都写进代码里了,所以这个 f(n) 功能的内部代码我们已经写好了。
这就是递归最重要的三要素,每次做递归的时候,你就强迫自己试着去寻找这三个要素。
实例1:
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(3)=2,F(n)=F(n-1)+F(n-2)(n>=4,n∈N*)
原文链接:https://blog.csdn.net/weixin_43328024/article/details/84769854
#include <iostream>
#include<iomanip>
using namespace std;
int main()
{
int i;
int N;
cout << "需要求多少项斐波那契数列:"<<endl;
cin >> N ;
long double f[1000] = {
1,1};//定义数组并初始化
for(i=2;i