递归的原理及用法
小贴士:
'0'+0='0';
'0'+1='1';
C
允许函数调用它本身,这种调用的过程称为递归。
在很多书看到的递归都是求阶乘,还有斐波那切。
这里写一个可以将一个整数打印成字符的函数。
void binary_to_asii(unsigned int value)
{
unsigned int quotient;
quotient=value/10;
if(quotient!=0)
brnary_to_asii(quotient);
putchar(value%10+'0')
}
如果输入4082,那么它会打印出4028
。
程序是这样执行的:先求出408,不为0,
再进入函数,求得,40,不为0,
再进入函数,求得4,不为0,
再进入求得0。
因为先前执行了四次,与所有调用函数一样,调用完要返回执行调用函数的下一条语句。也就是进入了四次,那么就要返回。
先输出4%10=4,
再40%10=0,
再408%10=8,
再4082%10=2。
所谓递归,就是先递进,再回归,递进是因为每次都要进入调用函数。而回归是因为每个函数都是顺序执行的。
原理
每一次的调用,都将会创建一批变量,它们将覆盖递归函数前一次调用所创建的变量,这个是在堆栈上进行的,可以看作一层一层的叠加。而我们达到了某一个条件时,它将把变量一层一层地销毁,让前一次调用继续执行,直到结束。
重点是调用到一个结束条件后,我们不再继续调用了,进而要顺序执行每一次调用的语句。
用法
- 确定目标
- 找到结束条件
- 找到关系式
例如:
算1到n的和
- 算从n到1的和
- 当n为1时,返回1
- n+sum(n-1)
int sum(int n)
{
if(n==1)
return 1;
return n+sum(n-1);
}
int sum(int n)
{
int ans=0;
if(n==1)
ans=1;
else
ans=n+sum(n-1);
return ans;
}
而这样每次都会创建新的变量,会消耗内存,所以可以用循环的尽量不要用递归。
用递归来算二进制可以很好的理解它
#include <stdio.h>
void dectobin( int n );
int main()
{
int n;
scanf("%d", &n);
dectobin(n);
return 0;
}
void dectobin( int n )
{
int ans=0;
ans=n%2;
if(n>=2)
dectobin(n/2);//n为1或0时就开始输出,正好是逆序的
printf("%d",ans==0?0:1);
return ;
}
比如我们输入5
时
dectibin(5)
前半段
void dectobin( int n )//n为5
{
int ans=0;
ans=n%2;//ans=1
if(n>=2)//n=5表达式为真
dectobin(n/2);//n/2=2,进入下面的dectobin(2)函数中
}
dectibin(2)
前半段
void dectobin( int n )//n为2
{
int ans=0;
ans=n%2;//ans=0
if(n>=2)//n=2表达式为真
dectobin(n/2);//n/2=1,进入到下面的dectobin(1)函数中
}
dectibin(1)
void dectobin( int n )//n为1
{
int ans=0;
ans=n%2;//ans=1
if(n>=2)//n=1为假
dectobin(n/2);
printf("%d",ans==0?0:1);//输出1
return ;//返回到dectibin(2)函数中
}
dectibin(2)
后半段
//ans=0
dectobin(n/2);//得到dectibin(1)的返回
printf("%d",ans==0?0:1);//输出0
return ;//返回到dectibin(1)函数中
dectibin(5)
后半段
//ans=1
dectobin(n/2);//得到dectibin(2)的返回
printf("%d",ans==0?0:1);//输出1
return ;//返回到main函数中的dectibin(n)中
可以看出printf
先后输出的是101
。
在数据结构与算法分析(C语言描述)中,这样说
递归绝不能作为简单的
for
循环的代替物。
四条基本法则
- 基准情形。有某些基础情形,不用递归都可以求解。
- 不断推进。递归调用必须能够朝着产生基准情形的方向前进。
- 设计法则。假设所有的递归调用都能运行。
- 合成效益法则(compound interest rule)。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。