不使用递归重写递归函数

发布于 2024-10-07 13:01:59 字数 203 浏览 2 评论 0原文

我正在重写一些现有的代码,其中递归调用不容易实现或不需要。 (在 Fortran 77 中,如果你必须知道的话。)我考虑过从头开始创建一个堆栈来跟踪所需的调用,但这看起来很笨拙,而且我宁愿不将内存分配给数组,以防递归不深。 (我也不相信 Fortran 77 支持动态数组大小调整。)

对于如何采用明显递归函数并以非递归方式重写它而不浪费堆栈空间的一般解决方案,还有其他建议吗?

I'm rewriting some existing code in a setting where recursive calls are not easily implemented nor desired. (And in Fortran 77, if you must know.) I've thought about making a stack from scratch to keep track of the calls needed, but this seems kludgy, and I'd rather not allocate memory to an array in cases where the recursion is not deep. (I'm not confident that Fortran 77 supports dynamic array sizing either.)

Any other suggestions for a general solution on how to take an obviously recursive function and rewrite it non-recursively without wasting space on a stack?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泡沫很甜 2024-10-14 13:01:59

如果您的代码使用尾递归(即函数直接返回每个递归调用的结果而不进行任何其他处理),那么可以在没有堆栈的情况下强制重写该函数:

function dosomething(a,b,c,d) 
{
  // manipulate a,b,c,d
  if (condition) 
    return dosomething(a,b,c,d) 
  else
    return something;
}

Into:

function dosomething(a,b,c,d) 
{
  while (true) 
  {
    // manipulate a,b,c,d
    if (condition) continue;
    else return something;
  }
}

没有尾递归,使用堆栈(或类似的方法)中间存储)是唯一的解决方案。

If your code uses tail recursion (that is, the function returns the result of every recursive call directly without any other processing) then it's possible to rewrite the function imperatively without a stack:

function dosomething(a,b,c,d) 
{
  // manipulate a,b,c,d
  if (condition) 
    return dosomething(a,b,c,d) 
  else
    return something;
}

Into:

function dosomething(a,b,c,d) 
{
  while (true) 
  {
    // manipulate a,b,c,d
    if (condition) continue;
    else return something;
  }
}

Without tail recursion, using a stack (or a similar intermediary storage) is the only solution.

慈悲佛祖 2024-10-14 13:01:59

可以写成循环的经典递归函数是斐波那契函数:

 function fib(n)
 {
     // valid for n >= 0
     if (n < 2)
         return n;
     else
         return fib(n-1) + fib(n-2);
 }

但是如果没有记忆,这需要 O(N) 堆栈空间的 O(exp^N) 操作。

它可以重写:

 function fib(n)
 {
     if (n < 2)
        return n;
     var a = 0, b = 1;
     while (n > 1)
     {
         var tmp = a;
         a = b;
         b = b + tmp;
         n = n - 1;
     }   
     return b;
 }

但这涉及到函数如何工作的知识,不确定它是否可以推广到自动过程。

The classic recursive function that can be written as a loop is the Fibonacci function:

 function fib(n)
 {
     // valid for n >= 0
     if (n < 2)
         return n;
     else
         return fib(n-1) + fib(n-2);
 }

But without memoization this takes O(exp^N) operations with O(N) stack space.

It can be rewritten:

 function fib(n)
 {
     if (n < 2)
        return n;
     var a = 0, b = 1;
     while (n > 1)
     {
         var tmp = a;
         a = b;
         b = b + tmp;
         n = n - 1;
     }   
     return b;
 }

But this involves knowledge of how the function works, not sure if it can be generalized to an automatic process.

2024-10-14 13:01:59

大多数递归函数可以很容易地重写为循环,至于浪费空间 - 这取决于函数,因为许多(但不是全部)递归算法实际上依赖于这种存储(尽管,在这些情况下循环版本通常更有效)也)。

Most recursive functions can be easily rewritten as loops, as to wasting space - that depends on the function, since many (but not all) recursive algorithms actually depend on that kind of storage (although, the loop version is usually more efficient in these cases too).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文