我正在练习递归,并编写了用于总结a+b的小代码,如下所示:
#include <stdio.h>
int b=6;
static int cnt;
void main(void)
{
int a=9,sum;
sum=succ(a);
printf("Sum returned : %d\n",sum);
}
int succ(x)
{
cnt++;
return(cnt<=b ? succ(x+1) : x++);
}
用这个我会得到很好的结果。有人能建议优化或更好的代码吗?我还想了解在这种情况下,变量cnt和x是如何堆叠的,它们是否成对堆叠,如0-9,1-10 ,2-11,3-12 ,4-13,最后当cnt为5时,从增量后返回x?
发布于 2013-07-30 09:26:04
首先,应该将main
声明为int main
。
其次,我建议将cnt
(我称之为iteration_number
)作为参数传递。此外,您应该避免使用全局(b
)。如果定义了助手函数,则不会更改函数的签名:
int add_helper(int value, int max, int iteration_number)
{
if (iteration_number >= max) return value;
return add_helper(value + 1, max, iteration_number + 1);
}
int add(int a, int b)
{
add_helper(a, b, 0);
}
请注意,我已经将您的b
重构为参数,我称之为max
。这个函数可以这样使用:
int main(void)
{
int start = 9; // Your a
int count = 6; // Your b
int sum = succ(start, count);
}
(如果您使用的是C89而不是C99或C11,那么在main()
的末尾应该有一个return 0;
)。
然而,递归定义加法的“好”方法是增加一个数,减少另一个数:
int add(int a, int b)
{
if (b == 0) return a;
return add(a + 1, b - 1);
}
修改函数以使用负数是留给读者的练习。
(注:通常您希望从最低的数字中减去,并将其添加到最大的值。为了保持示例紧凑性,我忽略了这一点。)
我还想了解在这种情况下,cnt和x变量是如何堆叠的。
通过“堆叠”,我假设您是指在调用函数时变量是如何被推入堆栈的。您的cnt
有静态链接,根本不被推到堆栈上。在我的示例中,每次调用都会将value
、max
和iteration_number
推到堆栈上。(据我所知,实现是如何定义的,取决于正在使用的调用约定。)换句话说,假设没有优化,参数将占用堆栈上的iteration_number * sizeof(int)
字节。
如果要跟踪这些值,只需使用在递归函数中打印它们,如下所示:
int succ_helper(int value, int max, int iteration_number)
{
if (iteration_number >= max) return value;
printf("%d: %d - %d\n", iteration_number, value, max);
return succ_helper(value + 1, max, iteration_number + 1);
}
有人能建议优化或更好的代码吗?
int sum = 9 + 6;
:-)
发布于 2013-07-30 10:21:26
“我还想了解变量cnt和x在这种情况下是如何堆叠的。它们是否成对堆叠,如0-9,1-10 ,2-11,3-12 ,4-13”
不,来自cnt
的值根本不在堆栈上。它是全局的,因此它将随着递归执行而改变。
“最后,当cnt是5时,它从增量后返回x?”
是的,它将返回x
的值,但是后置增量是没有意义的,因为变量从未与增量值一起使用。
通过在递归代码中使用全局变量,它没有正确地使用递归。只要您只有一个递归分支,它仍然可以工作,但是对于一个更复杂的任务,这些分支会使彼此的值混乱。
要正确使用递归,需要将所有数据发送到它需要的函数中:
void main(void) {
int a = 9, sum, b = 6;
sum = succ(a, b, 0);
printf("Sum returned : %d\n",sum);
}
int succ(int x, int y, int cnt) {
return cnt < y ? succ(x + 1, y, cnt + 1) : x;
}
然而,这并不是递归工作方式的一个很好的例子。通常,递归函数会将工作分成更小的部分,每个部分将递归地执行,而不是去除单个工作,然后递归地完成其余的工作。递归算法的深度不应该超过10或20个级别。当您使用递归只执行循环时,就像在示例中一样,它效率低下,并且很容易遇到堆栈溢出,从而导致更大的值。
https://codereview.stackexchange.com/questions/29166
复制相似问题