递归与局部变量混淆

时间:2016-10-08 13:27:30

标签: recursion

我正在尝试通过查看示例来提高我的递归技能(阅读书面递归函数)。但是,我可以很容易地获得没有局部变量的递归逻辑。在下面的示例中,我无法理解total变量的工作原理。我怎么能想到一个使用局部变量读写的递归函数?我认为这就像堆栈回击。顺便说一下,我写了没有变量的例子。我试着只写countThrees(n / 10);而不是total = total + countThrees(n / 10);,但它不起作用。

total变量:

int countThrees(int n) {
  if (n == 0) { return 0; }
  int lastDigit = n % 10;
  int total = 0;
  total = total + countThrees(n / 10);
  if (lastDigit == 3) {
    total = total + 1;
  }
  return total;
}

简化版

int countThrees(int x)
{
    if (x / 10 == 0) return 0;
    if (x % 10 == 3)
        return 1 + countThrees(x / 10);
    return countThrees(x / 10);
}

2 个答案:

答案 0 :(得分:0)

第一个条件应为:

if (x == 0) return 0;

否则单曲3将产生0。

在功能风格中,整个代码简化为:

return x == 0 ? 0
    : countThrees(x / 10) + (x % 10 == 3 ? 1 : 0);

关于本地变量:

int countThrees(int n) {
    if (n == 0) {
        return 0;
    }

    // Let an alter ego do the other digits:
    int total = countThrees(n / 10);

    // Do this digit:
    int lastDigit = n % 10;
    if (lastDigit == 3) {
        ++total;
    }
    return total;
}

原始代码有点未定,何时或做什么,比如在初始化为0后添加到总数。

通过在第一次使用时声明变量,事情变得更加清晰。

例如绝对懒惰:首先让递归实例计算其他数字的总和,然后才自己做最后一个数字。

使用只有一次使用的变量lastDigit并没有错;它解释了发生了什么:你检查最后一位数。

preincrement operator ++x; x += 1;x = x + 1;

其他人可以做到这一点(递归电话和自己的工作),所以它可能会说明作家的心理偏好

堆栈使用:是total 之前递归调用是堆栈上的额外变量。与数字无关。此外,智能编译器可以看到total是结果。

关于变量的用法:它们可以是有状态的,因此对于将递归转换为迭代非常有用。对于尾部递归是最简单的:递归发生在最后。

int countThrees(int n) {
    int total = 0;
    while (n != 0) {
        int digit = n % 10;
        if (digit == 3) {
            ++total;
        }
        n /= 10; // Divide by 10
    }
    return total;
}

答案 1 :(得分:0)

在这两种情况下,您都必须确实使用堆栈,但是当存在局部变量时,您需要在堆栈中放置更多空间,因为您需要将每个局部变量放入其中。在所有情况下,您跳转到新地点的行号也会存储。

所以,在你的第二个算法中,如果x = 13,那么堆栈将存储"第4行"在第一步,"第4行;第3行"在第二步中,在第三步中,您不会向堆栈添加任何内容,因为没有新的递归调用。在这一步结束时,您将读取堆栈(它是一个先进先出堆栈)以了解您必须前往的位置并删除第3行和第34行。从堆栈等等。

在您的第一个算法中,唯一的区别是您必须在堆栈中添加区域设置变量。因此,在第二步结束时,它看起来像"总计= 0,第4行;总数= 0,第4行和第34行。

我希望足够清楚。