一.函数递归?
1.递归是什么?
- 说白了递归就是函数自己调用自己。以下一个简单的递归。
#include<stdio.h>
int main()
{
printf("hehe\n");
main();
return 0;
}
代码最终会陷⼊死递归,导致栈溢出(Stack overflow)。
2.递归的思想
- 递归的思考方式就是把大事化小的过程。递归中的递就是递推的意思,归就是回归的意思。
递归在书写的时候,有2个必要条件:
-
递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
-
每次递归调用之后越来越接近这个限制条件。
二.第n个斐波那契数
1.什么是斐波那契数列
斐波那契数列(Fibonacci sequence):也被称为黄金分割数列,是一个著名的数列,由意大利数学家莱昂纳多·斐波那契所提出。这个数列的特点是从第三项开始,每一项都等于前两项之和。斐波那契数列的前几个数是:1、1、2、3、5、8、13、21、34等。这个数列在自然界中很常见,比如花的萼片和花瓣数量,以及某些植物的叶子排列,常常遵循这一规律。斐波那契数列也被应用于工程技术、科学计算、艺术创作等多个领域。
2.递归求解第n个斐波那契数
- 通过对斐波那契数列的了解,得出通项公式:
#include<stdio.h>
int Fib(int n)
{
if (n == 1 || n == 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int ret = Fib(8);
printf("%d\n", ret);//输出21
return 0;
}
3.迭代求解第n个斐波那契数
- 迭代也就是我们通常所说的循环,即用循环的方法来求第n个斐波那契数:
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 0;
while (n - 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int ret = Fib(8);
printf("%d\n", ret);//输出21
return 0;
}
4.递归与迭代的优缺点
如果仅仅从代码量上看,递归所写的代码少,简洁。但这能说明递归的效率高吗?其实不然,当你要求第50个斐波那契数的时候,你会发现递归迟迟给不出运行结果,而迭代秒出结果,就算是第100,1000,10000个斐波那契数,都是秒出结果。那这是什么原因呢?
其实,在递归法中,我们要求第50个斐波那契数,就要先求第49个和第48个斐波那契数,而要求第49个斐波那契数,又要先求第48个和第47个斐波那契数,要求第48个斐波那契数,就要先求第47个和第46个斐波那契数… 你会发现求出的结果任然要再求一遍,甚至第3,4,5…遍,导致递归效率非常低。而迭代只需一遍,效率远高于递归。
- 由此看出递归做了很多无用功,例如给出计算Fib(1)运行了多少次:
#include<stdio.h>
int count = 0;
int Fib(int n)
{
if (n == 1)
count++;
if (n == 1 || n == 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
Fib(50);
printf("count=%d\n", count);
return 0;
}
输出count=317811,这个数字已经很大了,当要求第50个斐波那契数的时候,计算机在不停的重复计算,导致迟迟出不了结果,这正是递归效率低的原因。
三.青蛙跳台阶问题
青蛙跳台阶:已知青蛙一次能跳一个或两个台阶,问青蛙跳到第50个台阶有多少种方法。
问题分析:
- 当青蛙要跳到第1个台阶时:只需一次跳一个台阶,有1种方法
Func(1)=1 - 当青蛙要跳到第2个台阶时:可以两次跳一个台阶,一次跳两个台阶,有2种方法
Func(2)=2 - 当青蛙要跳到第3个台阶时:有两种情况:1.先跳一个台阶,青蛙要跳到第2个台阶的方法 2.先跳两个台阶,青蛙要跳到第1个台阶的方法。Func(3)=Func(2)+Func(1)=3
- 当青蛙要跳到第4个台阶时:有两种情况:1.先跳一个台阶,青蛙要跳到第3个台阶的方法 2.先跳两个台阶,青蛙要跳到第2个台阶的方法。Func(4)=Func(3)+Func(2)=5
- 当青蛙要跳到第n个台阶时:有两种情况:1.先跳一个台阶,青蛙要跳到第n-1个台阶的方法 2.先跳两个台阶,青蛙要跳到第n-2个台阶的方法。
Func(n)=Func(n-1)+Func(n-2)
看到这里,你也许就豁然开朗了,其青蛙跳台阶就是典型的斐波那契数列问题,给出递归代码:
int Func(int n)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return Func(n - 1) + Func(n - 2);
}
int main()
{
int ret = Func(20);
printf("%d\n", ret);
return 0;
}