文章目录
名词解释
- 概念:函数调用自己本身实现循环的操作
- 死递归:递归没有明确条件限制,不断死循环,直到栈溢出
- 递归的好处:大幅缩减代码量,精简代码
- 递归的坏处:计算冗余,不适合复杂的代码使用递归
- 递归的主要思考方式:大事化小,思考每一小步的具体操作,用整体归纳法进行总结并不断尝试书写
练习:
用递归的思想,接受一个整型,并按顺序打印每一位。
思考流程:
- 想要达成按顺序打印每一位的大目标,就要思考如果把这个大目标拆分成小目标的话,每一小步应该怎么去进行?
- 如果按照从左到右依次打印,一时间显然想不到很好的办法,但是我们可以利用%(取模)和/(商)这两个符号,将整型拆分成一小块一小块的,然后逐个打印,这也就是所谓“大事化小”的思想。
预备知识: - /10:可以将整形的最后一位抹掉
- %10:可以只保留整型的最后一位
第一步,搭建大框架:
首先,我们先写出接受整型并调用函数的大框架:
void print(int n)//自定义函数print(不是printf!!)用于递归的操作
//由于我想直接在这个函数内打印,所以不需要返回值了,所以返回值是void,函数直接就把活干了,干完活自动销毁~
{
}
int main()
{
int n = 0;//定义一个变量,用于下文接受整形
scanf("%d", &n);//scanf用于接受整型
print(n);//调用自定义函数print,直接完成目标,大框架到此为止写完,下一步就是定义函数
return 0;
}
注意事项:
- 函数print的声明/定义需要在使用它之前,不要在使用后再声明/定义,但是可以先声明,再使用,再定义。
- 在自定义函数名时,要注意避免和已经有的关键字重名(如自定义成printf),否则会混淆或产生奇怪的bug。
第二步,如何实现函数:
- 接着,我们该继续完善print函数的定义了,它是如何实现的呢?
- 如果我们想要把这个大目标拆分成每次打印一个,这个小目标的话,那么,我们只需要思考,在这一小步里面,代码应该怎么写,就好了
- 显然,通过之前的预备知识,不难发现,我们最简单的选择就是先把整型的最后一位通过%10拆分出来并打印,然后再用/10将其抹掉,如此循环往复即可。
- 那么这个“循环”什么时候会停止呢?
- 当然是当n拆分到只剩一个数字的时候,循环就可以停止下来,直接开始打印了,那么我们需要设置一个限制条件,n只剩一个数字相当于什么?相当于n至少是两位数,也就是n>9的时候,需要进行拆分
- 当我们思考这个流程的时候,我们的思维是线性的,而递归的思维则是回旋镖式的。递归递归,先递出去,再归回来,顾名思义,这个操作是分去路和回路的,根据我们刚刚的构想,这里总不可能是先打印再拆分吧?当然是先拆分再打印了~所以去路是拆分的操作,回路是打印的操作。
代码示范:
void print(int n)
{
if (n > 9);//需要拆分的基本条件
print(n / 10);//调用此函数本身进行拆分(递出去),直到拆分到不能继续拆分,逐个打印(回归回来)
printf("%d ", n % 10);//打印最后一位数
}
至此,递归的函数写完了,我们用图像简单的演示一下这个函数的运行流程:
- 由于递归的图像演示比较大,建议使用电脑或平板观看,手机的话可以适当放大,按照箭头顺序观看。
- 通过图示可以发现,虽然递归的代码很精简,但是里面的运行还是有点东西的,需要初学者理解透彻,并不断练习,方可掌握这种思想的书写~
整体代码示范:
#include <stdio.h>
void print(int n)
{
if (n > 9)
print(n / 10);
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
print(n);
return 0;
}
写在最后
如果本文对您有帮助,可不可以给我一个小小的点赞呀❤~您的支持是我最大的动力。
博主小白一枚,才疏学浅,难免有所纰漏,欢迎大家讨论和提出问题,博主一定第一时间改正。
谢谢观看嘿嘿(๑•̀ㅂ•́)و✧~!