递归的基本原理

函数自己调用自己,这种调用的过程就叫递归。

递归的基本原理:

  • 每级函数调用都有自己的变量
  • 每次函数调用都会返回一次
  • 递归函数中位于递归调用之前的语句,按照被调函数的顺序执行
  • 递归函数中位于递归调用之后的语句,按照被调函数相反的顺序执行
  • 递归函数必须包含能让递归停止调用的语句。通常,用if语句或其他等价语句在函数形参等于某特定值时终止递归;因此每次递归调用的形参都要使用不同的值。

下面举一个例子,来帮助大家理解以上五个基本原理。

#include
void recursion(int n)//递归函数
{
	printf("这里第%d级递归\n", n);//递归调用之前的语句
	if (n < 4)//递归的终止条件
	{
		recursion(n + 1);
	}
	printf("打印的数字:%d;那么这就是第%d级递归的递归函数的形参。\n",n,n );//递归调用之后的语句
}
int main()
{
	recursion(1);//第一级调用
	return 0;
}

输出结果如下:

这里第1级递归
这里第2级递归
这里第3级递归
这里第4级递归
打印的数字:4;那么这就是第4级递归的递归函数的形参。
打印的数字:3;那么这就是第3级递归的递归函数的形参。
打印的数字:2;那么这就是第2级递归的递归函数的形参。
打印的数字:1;那么这就是第1级递归的递归函数的形参。

说明:

这个递归可以看作是:recursion (1) 调用recursion (2) , recursion (2) 调用recursion (3),recursion (3) 调用recursion (4)

因此被调函数的次序应为:recursion (1),recursion (2),recursion (3),recursion (4) 。

从输出结果可以清楚的看到:位于递归调用之前的这条语句

printf("这里第%d级递归\n", n);

正是按照被调函数的次序执行的

这里第1级递归
这里第2级递归
这里第3级递归
这里第4级递归

然而,位于递归调用后的这条语句

printf("打印的数字:%d;那么这就是第%d级递归的递归函数的形参。\n",n,n );

正如第4点原理所说的,是按照与被调函数相反的次序执行的

打印的数字:4;那么这就是第4级递归的递归函数的形参。
打印的数字:3;那么这就是第3级递归的递归函数的形参。
打印的数字:2;那么这就是第2级递归的递归函数的形参。
打印的数字:1;那么这就是第1级递归的递归函数的形参。

过程:

当recursion(4) 结束时,控制返回recursion(3) , 被调函数recursion(4) 把控制返回在调用的那个位置,因此,recursion(3)继续执行后面的代码。

然后当recursion(3)调用结束时,recursion(3)又把控制返回给recursion(2) , 继续执行其后的代码。

recurisn(2)以此类推。


尾递归tail recursion 

尾递归就是把递归置于函数的末尾,并且这种递归是最简单的递归形式,因为它相当于循环。


递归与倒序计算

递归在处理倒序时非常方便。比如我们写一个打印整数的二进制数的程序。

#include
void binary(long n)
{
	int r;
	r= n % 2;//得到最后一位二进制
	if (n >= 2)//如果n还大于等于2,说明还是二进制位;二进制只有0和1
	{
		binary(n / 2);//n/2相当于把二进制往前移一位
	}
	putchar(r == 0 ? '0' : '1'); //二进制偶数的末尾是0,集数的末尾是1

}
int main()
{
	unsigned long num;
	printf("请输出一个十进制数字。\n");
	scanf_s("%lu", &num);
	printf("它的二进制为:\n");
	binary(num);
	return 0;
}

打印结果如下

请输出一个十进制数字。
5
它的二进制为:
101

事实上

r=n%2;

这条语句计算的是,最后一位二进制位,这提示我们应该将这条语句写在递归调用之前

而把打印语句

putchar(r == 0 ? '0' : '1'); 

写在递归调用之后。

这样的话,计算的第一个值(最后一个二进制数)正好是最后一个打印。

  • 咱就是说,妙啊!

你可能感兴趣的:(c语言)