如何检测根递归调用?

Posted

技术标签:

【中文标题】如何检测根递归调用?【英文标题】: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)可以去那里。 【参考方案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;

【讨论】:

以上是关于如何检测根递归调用?的主要内容,如果未能解决你的问题,请参考以下文章

java数据结构二叉树查找结点操作,递归调用求详细讲解

bind测试递归及根区副本

OC中如何实现递归调用。

尾递归

尾递归

如何计算fibonacci函数的递归调用次数