目录
什么是递归?
程序调用自身的编程技巧称为递归。
把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归的主要思考方式在于:把大事化小
递归的两个必要条件
存在限制条件,当满足这个限制条件的时候,递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
递归的三要素
一、明确你这个函数想要干什么
对于递归,我觉得很重要的一个事就是,这个函数的功能是什么,要完成什么样的一件事,而这个,是完全由你自己来定义的。如:
// 求 n 的阶乘(n不为0)
int fun(int n)
{
}
二、寻找递归结束条件
所谓递归,就是会在函数内调用这个函数本身,所以,我们必须要找出递归的结束条件,否则就会死循环。
int fun(int n)
{
if(n == 1)
{
return 1;
}
}
三、找出函数的等价关系式
我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变,把大事化小。
int fun(int n)
{
if(n == 1)
{
return 1;
}
return fun(n-1) * n;
}
接受一个无符号整型值,按照顺序打印它的每一位。
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
print(num);
return 0;
}
求第 n 个斐波那契数。(不考虑溢出)
#include <stdio.h>
int Fib(n)
{
if (n <= 2)
{
return 1;
}
else
{
return n + Fib(n - 1);
}
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = Fib(num);
printf("%d\n", ret);
return 0;
}
当我们计算Fib(7)时,Fib(3)已经重复计算了5次,如果计算非常大的斐波那契数的时候,底层的计算量也是非常庞大的,计算时间也会是十几分钟或者几小时。
系统分配给程序的栈空间是有限的,但是有可能你不停地开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出。
那如何解决上述的问题:
将递归改写成非递归,即循环。
// 求 n 的阶乘
int fun(int n)
{
int tmp = 1;
while (n > 1)
{
tmp *= n;
n --;
}
return tmp;
}
这种写法就不会出现一个数字被重复计算很多次的情况。
注:
许多时候以递归的形式进行解答,这只是因为它比非递归的代码更简单。
当一个问题数据相当大的时候,用递归实现就非常不合理了,此时用循环实现便可以补偿它的问题
递归只是在某些特殊的情况下才会使用。
如果学过数据结构,就知道栈这种结构,函数的递归本来就是一种压栈,也是先进后出的。
想要掌握函数的递归,必须大量的练习。