繁体   English   中英

难以理解连续的递归调用

[英]difficulty in understanding successive recursive calls

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

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

如果有人可以就此提出建议,将不胜感激...

这种多次递归调用是否以任何方式有益或在特定问题领域找到应用..?

只需将自己置于 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() 的调用发生递归调用之后,例如调用

功能(“123”)

会像

  • 输入 func("123")
  • 不满足终止条件
  • 调用 func("23")
  • 再次调用 func("23")
  • printf("3")(这是一个[1])
  • 返回

发布的代码是一个设计相当糟糕的递归实例。

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

通过将反转的字符串传回 main 并让 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;
}

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

递归调用树

从图中可以看出,在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

递归可以简单理解如下。

例如:

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

假设a = 5

发生的情况是它返回5 * func(4)

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

查看此示例以了解在斐波那契数列中使用递归

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM