这篇重点介绍函数递归
目录
函数递归定义
首先,程序调用自身的编程技巧称为递归。那么函数递归就是函数在定义时调用函数自身的方法,递就是传递,归就是回归。递归的基本思想就是把规模大的问题转化为规模小的相似的子问题来解决。特别地,在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况。
举个例子:你在地铁站排队买票,排在你前面的人很多,你想知道你前面还有多少人,于是你问你前面的人是第几位,前面的人不知道,于是问他前面的人,由不知道,再继续问,以此类推,直至问到第一个人,这是递。第一个人说“是不是**,没看到我是第一个”,那么第二个人也知道了自己的位置,第三、第四以及后面的人都知道了自己的位置,最终你得到了你自己的位置,这是归。
递归的必要条件
-
需存在限制条件,当满足这个限制条件的时候,递归停止。
-
每次递归调用之后越来越接近这个限制条件
递归案例
1.接受一个无符号的整型n,按顺序打印每一位。例:输入4325,输出4 3 2 5
假设自定义一个函数print来完成,按照递归思想
print(4325)=print(432) 5=print(43) 2 5=print(4) 3 2 5,n的每一位可以用n%10和n/10循环完成,那么如何保证是按顺序打印?
我们来看函数内的数字,当print括号内数字为最高位数字的时候便开始打印,而最高位数字为个位数,所以n<10的时候开始打印,print代码如下:
void print(unsigned int n)
{
if(n>9)
print(n/10);
printf("%d",n%10);
}
代码详解如图:
那么最终答案也就出来了
2.递归实现strlen函数
既然是实现strlen函数,那么就先来看看strlen函数的功能和使用,strlen函数是用来求字符串长度的函数,形参和返回值如下:
strlen函数以"\0"作为结束的标志
假设自定义函数为len,那么函数参数和返回值便确定了
int len(char*p)
那如何求长度?
给定一个字符串"halo",还是依据递归的思想
len(halo)=1+len(alo)=1+1+len(lo)=1+1+1+len(o),当*p为“\0”时便停止
代码如下:
int len(char*p)
{
if(*p=='\0')
return 0;
else
return 1+len(p+1);
}
运行结果:
3.输入一个非负整数,返回组成它的数字之和。例:1729,1+7+2+9=19,结果返回19
自定义函数digitsum,根据题目要求可以确定参数和返回值
int digitsum(unsigned int n)
digitsum(1729)=digitsum(172)+9=digitsum(17)+2+9=digitsum(1)+7+2+9
括号内数字n/10完成,括号外n%10完成,当n<=9停止递归,代码如下:
int digitsum(unsigned int n)
{
if(n<=9)
return n;
else
return digitsum(n/10)+digitsum(n%10);
}
运行结果如下:
4.青蛙跳台阶
这是比较经典的题目了,青蛙一次可以跳1或2个台阶,问跳上n阶台阶有多少种跳法
假设f(n)表示:
n=1,此时只有一种跳法;f(1)=1
n=2,青蛙一次跳两个台阶或两次都跳一个台阶,共两种跳法;f(2)=2
n=3,假设青蛙第一次跳1个台阶,那么剩下的两个台阶就是n=2时青蛙的跳法,即f(2);假设青蛙第一次跳两个台阶,剩下的一个台阶就是n=1时的跳法,即f(1);所以f(3)=f(2)+(1)
n=4,同理,青蛙第一次跳一个台阶:f(3);青蛙第一次跳两个台阶f(2);f(4)=f(3)+f(2)
代码如下:
int f(int n)
{
if(n<=2)
return n;
else
return f(n-1)+f(n-2);
}
运行结果:
需要注意的是,递归在每一次调用函数的时候都会在栈区开辟一块新的空间,所以递归的层次不宜过深,否则栈区空间被占满就会导致占溢出(不信你试试求f(100) (〃 ̄ω ̄〃)),所以什么时候使用递归需酌情考虑。
如果觉得有帮助,记得点个赞