CSDN的同学们大家好,今天学习的内容是递归,递归其实也是一种函数,它的主要用途是大事化小,接下来就让我们来了解递归吧,let‘s go!
前言
程序调用自身的编程技巧称为递归( recursion)。
一、递归是什么?
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的
一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归策略
只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小。
二、递归的条件
1.练习和认识递归函数
代码如下:
#include<stdio.h>
void digui(int n)
{
if (n > 9)
{
digui(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
digui(n);
}
那么代码的执行流程是什么呢?
递归递归,递归是先递推再回归,先执行if语句表达式条件,一步一步分解到1,1小于9,不满足if语句表达式条件,1%10 输出 1,然后开始回归,1分解之前是12,然后12%10,输出2,再回归123,123%10,输出3,最后回归1234,1234%10,输出4。这就是递归思想。
比如我们要求n的阶乘和斐波那契数列
//求n的阶乘
int factorial(int n)
{
if(n <= 1)
return 1;
else
return n * factorial(n-1);
}
int main()
{
int n=0;
scanf("%d",&n);
factorial(n);
rerurn 0;
}
//求斐波那契数列 1 1 2 3 5 8 13.....
int fib(int n)
{
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main()
{
int n=0;
scanf("%d",&n);
fib(n);
return 0;
}
//但这两个递归函数是有问题,当n的输入超出一定的数值,会造成栈溢出,因为递推和归回,它的重复计算会包含很多次,这样会造成栈溢出。
我们可以看一看斐波那契数列的第三个数被重复计算了多少次。
#include <stdio.h>
int count = 0;//全局变量
int fib(int n)
{
if (n == 3)
count++;
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
fib(n);
printf("count=%d\n", count);
return 0;
}
我们可以看到当我们计算斐波那契数列的第30个数的时候,数列的第三个数被重复计算了317811次。所以在递归函数的参数比较大的时候,会造成栈溢出(stack overflow)。
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一
直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出。
那么我们该怎么样解决以上问题呢?就是把递归写成非递归。
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int a = 1; //1 1 2 3 5 8 13 21...
int b = 1;
int c = 0;
while (n >= 3) //限制计算一个数的条件
{
c = a + b;
a = b;
b = c;
n--; //每次判断
}
printf("%d\n", b);
}
2.递归的两个必要条件
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件。
可以看到上面的每个代码,都有一个限制条件,如果没有就会无限递归下去,造成死循环。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了递归函数的使用与讲解,而递归函数提供了递推和回归的计算,能使我们将大事化小。