【问题标题】:Difficulties in understanding this recursion理解这种递归的困难
【发布时间】:2016-10-14 21:05:54
【问题描述】:

我没有在 C++ 中得到这个递归练习。这里是:

int fatt(int x){
    int s=1; // here. since 's' will always be 1 shouldn't i get 1 as an output???
    if(x>1) { s = x*fatt(x-1); }
    return s;
}

int main()
{
    int n;
    cout << "Type a number: ";
    cin >> n;
    if (n < 0) { cout << "Error" << endl; }
    if (n <=1) { cout << "Factorial: 1" << endl; }
    else { cout << "Factorial: " << fatt(n) << endl; }
}

如果我输入s=0,它总是将我作为输出返回0,如果我输入 2,它会使结果加倍 O.o 我不明白它是如何工作的。我知道x 总是会减少直到达到 2 并且返回结果但是每次调用函数时不应该给 's' 的值 1???

【问题讨论】:

  • "'s' 不应该被赋予 1 的值???"是的,但是下一行给s 分配了其他东西,所以不,它并不总是返回 1。
  • 当你调用 fatt(3) 时,x 不会改变。 fatt(3) 的执行调用了 fatt(2),创建了一个新的上下文,其中另一个变量也名为 x,但不同。
  • 递归的可视化有时会有所帮助:mrlamont.com/uploads/1/7/0/2/17021682/factorial.png
  • 如果你理解了代码:你不需要做 if (n
  • 哇谢谢大家!图片实际上对我帮助很大! ^^

标签: c++ function recursion return


【解决方案1】:

假设你调用参数值为 3 的函数:它看起来像这样:

int fatt(3) {
    int s = 1;
    if (3 > 1) s = 3 * fatt(3 - 1);
    return s;
}

所以 s 是 3 * fatt(2) 的计算结果,fatt(2) 的结果是:

int fatt(2) {
    int s = 1;
    if (2 > 1) s = 2 * fatt(2 - 1);
    return s;
}

所以s是2 * fatt(1)的计算结果,fatt(1)的结果是:

int fatt(1) {
    int s = 1;
    if (1 > 1) s = 1 * fatt(1 - 1);  // False so this is never executed.
    return s;
}

fatt(1) 的结果是 1。所以这就是我们返回到 fatt(2) 的调用,然后转换为:

s = 2 * 1;

结果为 2,然后返回给fatt(3) 的调用,然后给出:

s = 3 * 2;

结果为 6。

请记住,每次执行函数时,局部变量 s 都会被压入堆栈。所以不是同一个变量。

如果您将 s 初始化为 2,那么第一行将显示为:s = 2 * 2;,函数的其余部分将给出结果值的两倍。由于s 确实是您最终乘以的因子,因此在您的阶乘中:

所以序列:3 * 2 * 1 变为 3 * 2 * 2

【讨论】:

  • 非常感谢!我终于明白了。我应该仔细看每一步,我会明白的^^。
【解决方案2】:

变量s 是函数fatt 的给定实例的局部变量。当函数递归调用自身时,每次调用都会获得自己的s 的新副本。这被初始化为 1,但不会影响堆栈中所有先前的 s 实例。然后在乘以 x 的本地副本之后,将其中的每一个分配给 fatt 调用的结果。

【讨论】:

  • 为什么 's' 成倍增加?我没有看到任何乘法,在 's' 之前有一个 '=' ???
  • 我编辑了答案,因为它不是很清楚。每个本地 s 都分配给(s 由下一次调用计算)* x。所以被乘以的s是从下一次调用开始的那个,即fatt(x-1)的结果
【解决方案3】:

's' 应该是 1,但它会被赋值,然后在函数完成时更改它所持有的值。

递归可能一开始有点难以理解,但一旦你理解了,它就很漂亮了。

我建议你用笔和纸。

1) 令 x = 3;

int fatt(3) {
    int s = 1;
    if (3 > 1) s = 3 * fatt(3 - 1);
    return s;} 

2) 在函数中 3>1 = true 所以它再次被传递,但这次是 (3-1) 即 2

注意:函数未执行完毕

3) 现在 x = 2

int fatt(2) {
    int s = 1;
    if (2 > 1) s = 2 * fatt(2 - 1);
    return s;}

4) 重复步骤 2) (2-1) 即 1

5) 由于在第三个函数调用中 x IS NOT > 1,这将导致 s 的返回

s = 1;
return s;

所以...

从第二个函数调用开始:

s = x * fatt(x-1);
s = 2 * 1;
return s;

第一次调用时再重复一次)

s = x * fatt(x-1);
s = 3 * 2;
return s;

把它想象成一堆函数

第一个堆栈 ------- 调用堆栈 2 并等待

2nd stack ----------调用堆栈3并等待

第一个堆栈 ---------- 等待

终于……

第 3 个堆栈 ---------- 条件不满足返回

第二个堆栈----------条件完成返回

第一个堆栈---------条件完成返回

希望有帮助

【讨论】:

    猜你喜欢
    • 2021-05-15
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多