【问题标题】:How to use return function in recursion如何在递归中使用返回函数
【发布时间】:2017-11-02 03:43:29
【问题描述】:

我有以下代码用于树的中序遍历:

void inOrder(struct node* r)
{
    if (r==NULL)
    return;

    else
    {
        inOrder(r->left);
        printf("%d ", r->value);
        inOrder(r->right);
    }
} 

我有这个愚蠢的疑问:

当最左下的孩子作为根传递时,它不为空。 在下一次迭代中,root 将为 null(因为最底部左孩子的左孩子将为 null)并且会遇到 return。

这个 return 语句不会将控制权传递给 main 函数(或调用它的任何地方)而不打印任何内容吗?

return 在递归中的行为是否不同?

【问题讨论】:

  • 你知道什么是函数调用栈吗?
  • @StoryTeller 我认为理解这一点不需要调用堆栈的概念,只需要函数调用和返回语句的基本语义
  • 递归函数的工作方式与所有其他函数完全一样。我想你可能认为递归是一种循环,但它是一个普通的函数调用。
  • @PasserBy - 显然它是必需的。否则,OP 不太可能对 return 语句将它们带到哪里感到困惑。
  • @StoryTeller 调用堆栈用于所有意图和目的,是一个实现细节,尽管是一个非常知名的细节。函数调用和返回语句是一个概念。例如,用调用堆栈解释 Haskell 中的函数调用是没有意义的。

标签: c++ recursion


【解决方案1】:

一个经典的递归例子可能更能说明问题

int factorial(int n)
{
    if(n == 0)
        return 1;
    return n * factorial(n - 1);
}

如果我们调用factorial(3),它将递归调用factorial,直到基本情况n == 0,此时,控制流将返回到它被调用的位置,即@ 987654325@ 而不是main

所以,不,您的 return 语句会返回到调用函数的父节点。

【讨论】:

    【解决方案2】:

    当最左下的孩子作为根传递时,它不为空。

    void inOrder(struct node* r)
     {
    if (r==NULL)
    return;
    
    else{
    inOrder(r->left);
    printf("%d ", r->value);
    inOrder(r->right);
    }
    
    } 
    

    在上面的代码中,当您将最左下角的孩子作为 root 传递时。

    它首先执行这一行

    if (r==NULL) return;
    

    因为r 当前不为空,它会跳过这个返回。

    在 else 部分它现在将执行

    else{
      inOrder(r->left);
    

    这里,它再次调用了同一个函数,所以当前执行将暂停片刻,并在此调用返回时恢复。

    现在,inOrder(r->left); 再次调用inOrder(struct node* r);,并将null 作为参数r 调用此调用。因为,你传递的是空的r->left

    所以,对inorder 的调用将到达return

    if (r==NULL) return;
    

    当它返回时,它将恢复上次暂停的 inorder 调用实例 inOrder(r->left); 来电。

    这是可能的,因为每当您从内部调用函数时 函数是维护一个call stack.

    现在,恢复后会执行下一行

    printf("%d ", r->value);

    这将打印最左下角节点中的值。

    最后,它会调用最后一行

    inOrder(r->right); 将再次暂停当前函数的执行,并在调用堆栈中保存函数的当前状态后,它将再次调用带有 null 的 inorder r->right,这将再次返回

    if (r==NULL) return;

    最后它会回到inorder 的原始执行并恢复,由于没有剩余指令,如果你从那里调用它会返回到main 方法并恢复main 中剩下的内容。

    所以,您的答案是它只会打印最左下角节点中的值。

    【讨论】:

      【解决方案3】:

      这个return 会将控制权传递回调用当前“层”函数的位置。

      函数调用被组织在一个称为堆栈的结构中。想象一下,您的计算机中有一个盒子。计算机可以将一个元素放入盒子中(在盒子中的其他元素之上),或者它可以移除盒子顶部的元素。考虑以下代码。

      void f(int x)
      {
          if (x == 0)
              return;
          f(x - 1);
      }
      

      如果你在主函数中调用f(2),计算机会将f(2)放入框内。当f(2)被执行时,它在函数内部调用f(1),因此计算机将f(1)放入盒子中(在f(2)之上)。由于f(1) 也调用f(0),计算机将f(0) 放入框内。

      f(0)被执行时,什么都没有被调用,它满足return指令。所以计算机从盒子中删除了f(0),而f(1)现在在盒子的顶部。所以你的计算机知道调用f(0)的是f(1)而不是main,所以它会继续执行f(1)。返回f(1)时也是一样。

      【讨论】:

      • 非常感谢您的详细解释。它使事情变得非常清楚。再次感谢!
      猜你喜欢
      • 2015-03-09
      • 1970-01-01
      • 2017-10-29
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 2018-11-13
      • 2022-01-16
      相关资源
      最近更新 更多