【问题标题】:How is this recursive function automatically converted into iterative function?这个递归函数是如何自动转换为迭代函数的呢?
【发布时间】:2011-08-29 12:55:33
【问题描述】:

我正在阅读如下尾递归

尾递归是指在最后一行进行递归调用。尾巴 递归可以通过将主体封闭在一个 while 循环并 用一个赋值替换递归调用 函数参数。

例如

void print(Iterator start, Iterator end, ostream& out=cout) {
  if(start == end)
      return;
  out << *start++ << endl;
  print(start, end, out);
}

通过上述规范转换为迭代为

void print(Iterator start, Iterator end, ostream& out=cout) {
   while(true) {
      if(start == end)
          return;
      out << *start++ << endl;
    }
}

在上面的段落中提到“用每个函数参数一个赋值替换递归调用,但在给定的示例中我们没有任何赋值?

谁能解释并举例说明如何将递归转换为迭代函数?

【问题讨论】:

  • 我认为他们说得不准确,他们真正的意思是你可以在每个循环中执行一次操作,而不是每个函数调用一次。在这种情况下,输出语句 (out &lt;&lt;)

标签: c++ recursion


【解决方案1】:

赋值隐藏在自增运算符中:

start++;

实际上是一个赋值:

start = start+1;

其实这个例子(第一部分)不是很好。

out << *start++ << endl;
print(start, end, out);

应该是

out << *start << endl;
print( start+1, end, out);

【讨论】:

  • 不正确。两个例子中都有这个任务。
  • @mydogisbox:我编辑了答案以显示“典型”递归调用。
  • 很好的澄清 - 原始示例用完全相同的分配“替换”一个分配非常令人困惑。
【解决方案2】:

我不认为,您所指的任何段落都很重要;只关注主要问题,您希望将递归函数转换为普通迭代函数,这可以(毫不费力地)完成,

void print(Iterator start, Iterator end, ostream& out=cout) {
   while(start != end) {
      out << *start++ << endl;
    }
}

【讨论】:

    【解决方案3】:

    它在 C++ 中隐藏了一点,但start++ 正在为循环中的每个时间分配一个新值。

    【讨论】:

    • 不正确。两个例子中都有这个任务。
    【解决方案4】:

    他们在谈论的是,您将尾部函数调用的参数分配给此函数调用的参数变量,但在这种情况下,它不是必需的,因为您使用完全相同的参数调用函数 (因为就像其他人说的,第一个参数start的变化发生在函数调用之前)。

    其实,如果做的准确,迭代函数应该是这样的

    void print(Iterator start, Iterator end, ostream& out=cout) {
        while(true) {
            if(start == end)
                return;
            out << *start++ << endl;
    
            start = start;
            end = end;
            out = out;
        }
    }
    

    但这些分配完全没有必要,即使在预期上是正确的。

    【讨论】:

      【解决方案5】:

      递归到迭代的一般转换如下所示。

      原码:

      void print(Iterator start, Iterator end, ostream& out=cout) {
        if(start == end)
            return;
        out << *start++ << endl;
        print(start, end, out);
      }
      

      转换后的代码:

      void print(Iterator start, Iterator end, ostream& out=cout) {
        while(true) {
           if(start == end)
              return;
           out << *start << endl;
      
           // One assignment per function argument for 'general' tail recursion
           start = start + 1;       // (1)
           end = end;               // (2)
           out = out;               // (3)
        }
      }
      

      包括解释中的三个作业。赋值 (1) 嵌入在 start++ 中,赋值 (2) 和 (3) 被优化掉。

      【讨论】:

      • 好吧,如果你想对转换非常严格,第二个代码应该在输出表达式中增加start(和第一个一样),然后在末尾简单地做start = start循环。这就是为什么该示例选择不当的原因,它在递归调用中传递参数时不会修改参数...
      猜你喜欢
      • 2020-08-08
      • 2015-05-30
      • 2021-11-03
      • 2020-08-20
      相关资源
      最近更新 更多