关于递归(以一道题为例)输出一个整数的每一位

题目:输出一个整数的每一位


说明:这里暂且不考虑负数的情况,只考虑正数

第一个代码:

思路:先考虑最极端的情况,当为一位数时,不再递归下去,输出当前数字;否则不断调用自身(参数中要依次丢弃每一位)

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num);
	}

	Printnum(num / 10);
}


int main()
{
        int num = 0;
	scanf("%d", &num);
	Printnum(num);
}

 具体递归调用步骤

可以看到结果就是栈溢出。为什么会这样呢?因为程序执行的是“步骤”按“步骤”顺序执行,以12为例,当num等于1时,进入if语句,输出1;然后顺序执行Printf(num/10),这时传入的参数就变成了0,于是继续调用函数,if条件满足,输出0,然后执行Printf(num/10)。因为参数一直为0,所以不断输出0,然后再顺序调用,往复循环没有出口。

错的点是:递归始终没有返回上一层。P(12)-->P(1)--->P(0)--->P(0)--->P(0)。。。。。

认识到上个代码存在的问题,于是改为这样--->

第二个代码:

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num);
	}
	else
	{
		Printnum(num / 10);
	}
}

 具体递归调用步骤

 可以看到结果只输出1。为什么呢?以12为例,当num等于1时,进入if语句,输出1;接下来不会进入else语句,但是会返回到递归的上一层,即Printnum(12),-->[要注意的是,这一层执行完后,递归就都结束了];直接跳出函数(注意不会执行里面的else语句)。所以最终只会输出1

再看这个-->(与第一个写法类似,就是print语句稍有不同)

第三个代码:

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num%10);
	}
	Printnum(num / 10);
}

与第一个一样,错的点都是:递归始终没有返回上一层。P(12)-->P(1)--->P(0)--->P(0)--->P(0)。。。。。

反思+总结:

递归一定是把握一个原则:“出口。”对于“出口”的理解,不是简单的不满足递归条件而“出”,而是从“大-->小>--大>”,一个大问题逐步分解为小问题,再小,直到最小的问题得到解决;然后再由小到大,依次一层层返回;最终到原点。


正确代码:

// 输出一个整数的每一位。
void Printnum(int num)
{
	if (num > 9)
	{
		Printnum(num / 10);
	}
	printf("%d ", num % 10);
}

过程:P(12)-->P(1)-->最小问题解决-->P(12)-->函数结束

输出结果: