我正在尝试通过查看示例来提高我的递归技能(阅读书面递归函数)。但是,我可以很容易地获得没有局部变量的递归逻辑。在下面的示例中,我无法理解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);
}
答案 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行。
我希望足够清楚。