提问者:小点点

理解这个递归函数[关闭]


编辑问题以包括所需的行为、特定的问题或错误以及重现问题所需的最短代码。这将有助于其他人回答问题。

#include <stdio.h>
void e(int );      
int main( ) 
{   
    int a;    
    a=3;    
    e(a); 
    return 0;
}    

void e(int n)  
{    
    if(n>0)   
    {
        e(n-1); 
        n = n-1;     
        printf("%d" , n);      
        e(n-1);  
        n = n-1; 
    }    
} 

我不明白这是如何计算为0120的,因为我认为如果它是0,if语句将不会运行……我知道我不擅长编码,但想知道是否有人可以解释它是如何输出0120的。


共2个答案

匿名用户

像这样的简单程序可以通过一些打印来“增强”以供理解。

您的原始:

// original
void e(int n)
{
   if(n>0)
   {
      e(n-1);
      n = n-1;
      printf("%d" , n);
      e(n-1);
      n = n-1;
   }
}

并且它的输出是相同的(即使使用c编译)

// 0120

这是非常相似的递归代码,还有几个指纹

// with debug prints
void e2(int n, std::stringstream& ss)
{
   static size_t seq = 0;
   std::cout << "seq=" << ++seq << " e2() " << "  n=" << n << std::endl; // invocation sequence
   if(n>0)
   {
      e2(n-1, ss);
      n = n-1;
      ss << "n= " << n << " " << std::flush;
      e2(n-1, ss);
      n = n-1;
   }
   else
      std::cout << "seq=" << seq << " e2()   else " << n << std::endl;
}

以及使用的调用:

int t267(int argc0)
{
   std::cout << "argc0: " << argc0 << std::endl << std::endl;

   int a = 3;

   std::cout << "\ne()----------------------------" << std::endl;
   e(a);

   std::cout << "\ne2()----------------------------" << std::endl;
   std::stringstream ss;
   ss << "e2: " << std::endl;
   e2(a, ss);
   std::cout << ss.str() << std::endl;
   std::cout << "\n----------------------------" << std::endl;

   return(0);

} // int t267(void)

一些中间输出:

seq=1 e2()   n=3
seq=2 e2()   n=2
seq=3 e2()   n=1
seq=4 e2()   n=0
seq=4 e2()   else 0
seq=5 e2()   n=-1
seq=5 e2()   else -1
seq=6 e2()   n=0
seq=6 e2()   else 0
seq=7 e2()   n=1
seq=8 e2()   n=0
seq=8 e2()   else 0
seq=9 e2()   n=-1
seq=9 e2()   else -1

ss捕获所有n=x以更简单的方式报告它们,而不是在调试cout之间交错。ss的输出:

n= 0 n= 1 n= 2 n= 0   

注意:这显示与原始数字序列相同

它还显示发生了9次递归调用。(seq=9)
这是你所期望的吗?

…调试打印通常也可以提供足够的信息来观察和修复编码错误。

接下来尝试a=0,或1,或2,或4,…等等。并尝试添加额外的打印。
练习。

并逐步审查中间输出,看看它是如何工作的。

祝你好运。

匿名用户

要理解递归函数,你必须首先认真理解递归:),尽管去阅读维基百科页面和你能找到的任何其他文章。https://en.wikipedia.org/wiki/Recursion

这里要记住的重要一点是,对e的每次递归调用都会增加您的调用堆栈,一旦您返回,您就会从调用堆栈中弹出最后一帧并返回到您上次调用e的位置。

以下是在您的案例中实际发生的步骤以及为什么它会这样做。调试器还将让您完成此操作:)

  1. e被叫3
  2. 3