递归是什么?
递归,顾名思义,就是递推和回归。
递归是一种解决问题的方法,在C语言中,递归就是函数自己调用自己。
#include <stdio.h>
int main()
{
printf("hehen");
main();//main函数中⼜调⽤了main函数
return 0;
}
上面就是C语言最简单的递归代码。但是这种代码最终会陷入死递归,导致栈溢出(Stack overflow)。
递归的核心是思想和限制条件:
1、思想:把一个大型复杂的问题层层转化为一个与原问题相似,但规模较小的子问题来求解;直到子问题不能再拆分,递归就结束了。所以递归的思考方式就是把大事化小的过程。
2、递归在书写时,有了两个必要条件:一是递归要存在限制条件,当满足这个限制条件,递归结束。二是每次递归调用之后越来越接近这个限制条件,避免死递归。
递归举例
例1:求n的阶乘
运算过程:
当我们输出n为5之后,把5带入函数中,n为5,所以会返回5*Fact(4),而Fact(4)的值我们并不知道,同样需要带入计算,Fact(4)= 4 * Fact(3),依次进行下去,知到n = 0时返回1。我们的结果就是5*4*3*2*1*1 = 120.
#include <stdio.h>
int Fact(int n)
{
if(n==0)
return 1;
else
return n*Fact(n-1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fact(n);
printf("%dn", ret);
return 0;
}
这里的n不能太大,否则会出现溢出。
例2:顺序打印⼀个整数的每⼀位
%10
和 /10 操作,直到1234的每⼀位都得到。
这⾥有个问题就是得到的数
字顺序是倒着的,所以我们需要先回归最高位的数,那么就要先递推最低位的数,与我们上面思考的过程不谋而合。
Print(n)如果
n
是
1234
,那表⽰为 Print(
1234
)
//
打印
1234
的每⼀位其中
1234
中的
4
可以通过
%
10
得到。那么 Print(
1234
)
就可以拆分为两步:1.
Print(
1234
/
10
)
//
打印
123
的每⼀位2.
printf
(
1234
%
10
)
//
打印
4完成上述
2
步,那就完成了
1234
每⼀位的打印那么
Print(
123
)
⼜可以拆分为
Print(
123
/
10
) +
printf
(
123
%
10)这样递推下去就能看出:
Print(
1234
)==>Print(
123
) +
printf
(
4
)==>Print(
12
) +
printf
(
3
)==>Print(
1
) +
printf
(
2
)==>
printf
(
1
)直到被打印的数字变成⼀位数的时候,就不需要再拆分,递归结束。
代码如下:
void Print(int n)
{
if(n>9)
{
Print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int m = 0;
scanf("%d", &m);
Print(m);
return 0;
}
这里要再强调一下,上述 print 函数是当到达限制条件后递推结束,才开始回归,所以最后推出的1是先打印的。
递归与迭代
通过上面的举例,我们可以看出递归是一种很好的编程技巧,但是代码简洁的背后,是庞大的计算量。以代码举例1为例:Fact函数是可以产⽣正确的结果,但是在递归函数调⽤的过程中涉及⼀些运⾏时的开销。
在C语⾔中每⼀次函数调⽤,都要需要为本次函数调⽤在栈区申请⼀块内存空间来保存函数调⽤期间的各种局部变量的值,这块空间被称为运⾏时堆栈,或者函数栈帧。
函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归
函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。所以如果采⽤函数递归的⽅式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stack overflow)的问题。
所以如果不想使⽤递归就得想其他的办法,通常就是迭代的⽅式(通常就是循环的⽅式)。
⽐如:计算n的阶乘,也是可以产⽣1~n的数字累计乘在⼀起的。
int Fact(int n)
{
int i = 0;
int ret = 1;
for(i=1; i<=n; i++)
{
ret *= i;
}
return ret;
}
事实上,我们看到的许多问题是以递归的形式进⾏解释的,这只是因为它⽐⾮递归的形式更加清晰,但是这些问题的迭代实现往往⽐递归实现效率更高。当⼀个问题⾮常复杂,难以使⽤迭代的⽅式实现时,此时递归实现的简洁性便可以补偿它所带来的运⾏时开销。
举例3:求第n个斐波那契数
#include <stdio.h>
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);
int ret = Fib(n);
printf("%dn", ret);
return 0;
}
#include <stdio.h>
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while(n>2)
{
c = a+b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%dn", ret);
printf("ncount = %dn", count);
return 0;
}
原文地址:https://blog.csdn.net/zy1215058242/article/details/136005813
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_66295.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!