难以理解连续的递归调用

时间:2015-07-20 16:55:21

标签: c recursion stack

我正在尝试理解以下程序,其中存在连续的递归函数调用,但在跟踪如何加载大头钉时会感到困惑。

void func(char*);  // function prototype

int main(){
    func("123");
    return 0;
}

void func(char a[]){
    if(a[1]=='\0')
        return;
    func(a+1);
    func(a+1);
    printf("%c",a[1]);
}

此输出为3 3 2

如果有人能就这一个提出建议,

会很感激...

这种多重递归调用是否有益于任何方式或在特定问题区域中找到应用程序..?

4 个答案:

答案 0 :(得分:2)

只需将自己放在CPU的位置并逐行执行(或使用调试器来帮助完成该任务)。

第一个电话是

func("123")

此调用不满足终止条件a[1] == '\0',因此调用

func("23");

对func(“23”)的调用依次调用

func("3")

满足返回条件。因此,该调用返回到前一个调用者func(“23”)。

由于这些行,

func(“23”)继续再次调用func(“3”)

func(a+1);
func(a+1);

在脑海中继续执行该程序的过程,并记下每次调用printf时的内容。这将解释你的输出。

更新

请注意,在递归调用之后,对printf()的调用会发生,例如致电

FUNC( “123”)

会像

那样进行
  • 输入func(“123”)
  • 未达到终止条件
  • 调用func(“23”)
  • 再次调用func(“23”)
  • Printf(“3”)(即[1])
  • 返回

答案 1 :(得分:1)

发布的代码是一个设计得很差的递归实例。

以下代码具有正确的尾部'递归的形式。

通过将反向字符串传递回main并让主要打印它,可以做得更好。

它反转main()

传递给func()的字符串的顺序

请问,在询问运行时问题时,请为编译发布代码,包括头文件的必要#includes,这样我们就不会猜测要包含哪些标题

#include <stdio.h>

void func(char*);  // function prototype

int main(){
    func("123");
    return 0;
}

void func(char a[])
{
    if(a[1]=='\0')   // check for end of recursive sequence
    {
        printf( "%c", a[0] ); // last tail action
        return;
    }

    func(a+1);    // step+next recursion
    printf( "%c", a[0] ); // tail action
    return;
}

答案 2 :(得分:1)

使用断点进行调试是了解递归的一种方法。另一种方法是绘制递归调用树。

Recursive calls tree

从图中可以看出,在level0之后的每个级别中,由于这两行代码,printf语句出现在每两个节点之后:

func(a+1);
func(a+1);

通常,对于任何长度大于0的输入字符串,这都会成为完美的二叉树。节点的总数由以下公式给出:

2^(k+1) - 1 // k is the depth; here k = 2

执行的printf语句总数可以通过以下公式获得:

2^k - 1 // For k=2, there will be 3 printf statements each printing 3,3,2 respectively

答案 3 :(得分:0)

递归可以简单地理解如下。

例如:

Func(int a){
    while(a>1)
        return a * func(a-1);
}

假设a = 5

它会返回5 * func(4)

现在func(4)会返回4 * func(3)并继续这样做。

查看this example for use of recursion in fibonacci series