[英]C recursion : return statement
我刚开始学习C,却遇到了以下问题:在第一步/ 递归步骤中 /我不明白为什么我们不能简单地返回乘法(x,y) ? 为什么我们需要向y添加一个值,然后才返回它?
代码如下。 谢谢!
#include <stdio.h>
unsigned int multiply(unsigned int x, unsigned int y)
{
if (x == 1)
{
/* Terminating case */
return y;
}
else if (x > 1)
{
/* Recursive step */
return y + multiply(x-1, y);
}
/* Catch scenario when x is zero */
return 0;
}
int main() {
printf("3 times 5 is %d", multiply(3, 5));
return 0;
}
如果返回乘法(x,y) ,则将在相同的调用参数上永远循环。 为了进行适当的递归,您必须将问题简化为更简单的情况。 最简单的情况是将乘数减1。
递归只是使用较小的输入执行相同的操作。 我们可以用较小的数字表示两个数字的乘法吗? 当然可以! 找到做到这一点的方法是找到乘法的递归定义。 首先,我们将尝试用较小的x(如x-1)表示x * y。 从简单的事实来看:
(x-1)*y = x*y - y
我们发现 :
x*y=(x-1)*y + y
请记住,我们将始终必须找到一个停止的步骤,在这里我们知道
0*y=0
我们完成了。 与@RobertEagle给出的形式相比,这给我们提供了一种更为简单的递归mul函数形式。
但是,让我们更进一步。 x-1小于x,因为y-1小于y。 探索这个事实使我们:
(x-1)*(y-1)=x*y-x-y+1
x*y = (x-1)*(y-1) + x + y - 1
这次停止步骤将是“如果x或y为0,则结果为0”。 将其转换为代码:
unsigned multiply(unsigned x, unsigned y)
{
if ( (x==0) || (y==0) )
return 0;
else
return x+y-1+multiply(x-1, y-1);
}
这种递归效率不高,因为我们没有用更小的东西来表示递归。 如果我们尝试将参数之一减半怎么办? 如果x是偶数,我们可以写:
x*y=2*(x/2)*y=(x/2)*(2*y)
如果x是奇数,我们可以写:
x*y=(x-1+1)*y=(x-1)*y+y=((x-1)/2)*(2*y)+y
左移(分别为右)可实现乘以(分别为2):
unsigned multiply(unsigned x, unsigned y)
{
if (x==0)
return 0;
else if (x%2==0)
return multiply(x>>1, y<<1);
else
return y+multiply((x-1)>>1, y<<1);
}
与第一个方法相比,此方法将花费更少的步骤。 通常,您变得越来越小,变得越来越快。
如果未添加该值,则它将仅返回y
作为最递归调用的最终结果。
X * Y = X,Y倍
例如4 * 5 = 4 + 4 + 4 + 4 + 4
这种逻辑正在扩展该求值,并且仅返回最后一个值将仅求值Y一次。
每个递归函数都由2个元素组成:
没有停止条件,程序将进入无限循环。 在这种情况下,这意味着程序将继续调用x == 1
。
除了停止在x == 1
处调用自身之外,该程序还将调用multiply(-1,y)
, multiply(-2,y)
...为无穷大。
最终,您需要将y相加x倍。 为此,您需要返回x乘以y的值。 在这种情况下,重复条件将y加 x到1倍,对于停止条件,您只需要再增加一次。
您也可以这样进行:
#include <stdio.h>
unsigned int multiply(unsigned int x, unsigned int y)
{
if (x == 0)
{
/* Terminating case */
return 0;
}
else if (x > 0)
{
/* Recursive step */
return y + multiply(x-1, y);
}
}
int main() {
printf("3 times 5 is %d", multiply(3, 5));
return 0;
}
在这里,您可以看到重复项与y恰好相加x倍。 从逻辑上讲,停止条件需要返回0,因为我们不再需要添加y值。 我们已经添加了x次。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.