【问题标题】:How to detect the root recursive call?如何检测根递归调用?
【发布时间】:2011-02-11 03:47:56
【问题描述】:

假设我们正在编写一个简单的递归函数fib(n),它计算第n 个斐波那契数。现在,我们希望函数打印第 n 个数字。由于重复调用相同的函数,因此必须有一个条件,只允许根调用打印。问题是:如何在不传递任何额外参数或使用全局/静态变量的情况下编写此条件。

所以,我们正在处理这样的事情:

int fib(int n) {
    if(n <= 0) return 0;
    int fn = 1;
    if(n > 2) fn = fib(n-2) + fib(n-1);
    if(???) cout << fn << endl;
    return fn;
}

int main() {
    fib(5);
    return 0;
}

我认为根调用不同于所有子调用,因为它返回到不同的调用者,即本例中的 main 方法。我想知道是否可以使用这个属性来写条件以及如何写。

更新:请注意,这是一个人为的示例,仅用于展示这个想法。从标签中应该可以清楚地看到这一点。我不是在寻找标准解决方案。谢谢。

【问题讨论】:

  • 正如许多答案中所指出的,通常的做法是创建一个启动递归的包装函数。自定义前/后处理(如 IO)可以去那里。

标签: c recursion stack


【解决方案1】:

我认为您可以从堆栈中获取返回地址,并以某种方式将其与 fib 函数的地址进行比较。返回地址应该靠近参数 n ,除非 n 在某个寄存器中传递,但在标准 C 中它不应该。您只需要知道返回地址相对于参数的位置。

【讨论】:

    【解决方案2】:

    我这样做的方法是使用辅助函数:

    int _fib(int n) {
        if(n <= 0) return 0;
        int fn = 1;
        if(n > 2) fn = _fib(n-2) + _fib(n-1);
        return fn;
    }
    
    int fib(int n) {
        int fn=_fib(n);
        cout << fn << endl;
        return fn;
    }
    

    或者,你可以这样写(c++):

    int fib(int n, bool f=true) {
        if(n <= 0) return 0;
        int fn = 1;
        if(n > 2) fn = fib(n-2, false) + fib(n-1, false);
        if(f) cout << fn << endl;
        return fn;
    }
    

    【讨论】:

    • 不错的一个。我暂时忘记了默认参数。
    • 顺便说一句,您的第一个解决方案不是打印所有内容吗?似乎函数 _fib 应该调用自己,而不是 fib。
    【解决方案3】:

    这里有一个棘手的方法,虽然我不确定这是否值得:):

    int fib(int n) {
    //    if(n <= 0) return 0;
        int isRoot;
        if ( n <= 0 ){
            isRoot = 1;
            n = -n;
        }
        else isRoot = 0;
        int fn = 1;
        if(n > 2) fn = fib(n-2) + fib(n-1);
        if(isRoot) cout << fn << endl;
        return fn;
    }
    
    int main() {
        fib(-5);
        return 0;
    }
    

    但是,该函数要求您并不是真的要发送负值:)。

    【讨论】:

      【解决方案4】:

      如果你真的想问 C 是否可以访问某种 API 以允许函数体中的代码找出调用执行函数的位置,答案是 。。 p>

      【讨论】:

      • 没错,但是you(就像在程序员中一样)可以修饰调用以找出它们来自哪里。
      【解决方案5】:

      根递归调用是调用递归的点,即main中的调用。鉴于此,您可以稍微重写您的代码(类似这样):

      int fib(int n) {
          if(n <= 0) return 0;
          int fn = 1;
          if(n > 2) fn = fib(n-2) + fib(n-1);
          return fn;
      }
      
      int main() {
          cout << fib(5) << endl;
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        • 1970-01-01
        • 2013-06-19
        • 1970-01-01
        • 1970-01-01
        • 2012-06-23
        相关资源
        最近更新 更多