首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归a+b函数

递归a+b函数
EN

Code Review用户
提问于 2013-07-30 08:48:58
回答 2查看 1.5K关注 0票数 4

我正在练习递归,并编写了用于总结a+b的小代码,如下所示:

代码语言:javascript
运行
复制
#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?

EN

回答 2

Code Review用户

回答已采纳

发布于 2013-07-30 09:26:04

首先,应该将main声明为int main

其次,我建议将cnt (我称之为iteration_number)作为参数传递。此外,您应该避免使用全局(b)。如果定义了助手函数,则不会更改函数的签名:

代码语言:javascript
运行
复制
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。这个函数可以这样使用:

代码语言:javascript
运行
复制
int main(void)
{
    int start = 9; // Your a
    int count = 6; // Your b

    int sum = succ(start, count);
}

(如果您使用的是C89而不是C99或C11,那么在main()的末尾应该有一个return 0; )。

然而,递归定义加法的“好”方法是增加一个数,减少另一个数:

代码语言:javascript
运行
复制
int add(int a, int b)
{
    if (b == 0) return a;

    return add(a + 1, b - 1);
}

修改函数以使用负数是留给读者的练习。

(注:通常您希望从最低的数字中减去,并将其添加到最大的值。为了保持示例紧凑性,我忽略了这一点。)

我还想了解在这种情况下,cnt和x变量是如何堆叠的。

通过“堆叠”,我假设您是指在调用函数时变量是如何被推入堆栈的。您的cnt有静态链接,根本不被推到堆栈上。在我的示例中,每次调用都会将valuemaxiteration_number推到堆栈上。(据我所知,实现是如何定义的,取决于正在使用的调用约定。)换句话说,假设没有优化,参数将占用堆栈上的iteration_number * sizeof(int)字节。

如果要跟踪这些值,只需使用在递归函数中打印它们,如下所示

代码语言:javascript
运行
复制
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);
}

有人能建议优化或更好的代码吗?

代码语言:javascript
运行
复制
int sum = 9 + 6;

:-)

票数 4
EN

Code Review用户

发布于 2013-07-30 10:21:26

“我还想了解变量cnt和x在这种情况下是如何堆叠的。它们是否成对堆叠,如0-9,1-10 ,2-11,3-12 ,4-13”

不,来自cnt的值根本不在堆栈上。它是全局的,因此它将随着递归执行而改变。

“最后,当cnt是5时,它从增量后返回x?”

是的,它将返回x的值,但是后置增量是没有意义的,因为变量从未与增量值一起使用。

通过在递归代码中使用全局变量,它没有正确地使用递归。只要您只有一个递归分支,它仍然可以工作,但是对于一个更复杂的任务,这些分支会使彼此的值混乱。

要正确使用递归,需要将所有数据发送到它需要的函数中:

代码语言:javascript
运行
复制
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个级别。当您使用递归只执行循环时,就像在示例中一样,它效率低下,并且很容易遇到堆栈溢出,从而导致更大的值。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/29166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档