Переписать рекурсивную функцию без использования рекурсии

StackOverflow https://stackoverflow.com/questions/4422032

Вопрос

Я переписываю какой-то существующий код в настройке, где рекурсивные вызовы не легко реализованы и не желательны. (А в Фортране 77, если вы должны знать.) Я думал о том, чтобы сделать стек с нуля, чтобы отслеживать необходимые звонки, но это кажется Kludgy, и я бы предпочел не выделить память в массив в случаях, когда Рекурсия не глубокая. (Я не уверен, что Fortran 77 поддерживает размывание динамического массива.)

Любые другие предложения для общего решения о том, как предпринять очевидно рекурсивное функцию и переписать его нерешительно, не тратя пространство на стеке?

Большое спасибо, старый McSt

Это было полезно?

Решение

Если ваш код использует рекурсию хвоста (то есть функция возвращает результат каждого рекурсивного вызова непосредственно без какой-либо другой обработки), то можно домельно переписать функцию без стека:

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

В:

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

Без рекурсии хвоста, используя стек (или аналогичное промежуточное хранение) - единственное решение.

Другие советы

Классическая рекурсивная функция, которая может быть записана в виде петли, является функцией Fibonacci:

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

Но без воспоминания это принимает операции O (Exp ^ n) с пространством O (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;
 }

Но это включает в себя знание того, как работает функция, не уверена, что она может быть обобщена в автоматическом процессе.

Большинство рекурсивных функций могут быть легко переписаны в виде петлей, чтобы тратить пространство - это зависит от функции, поскольку многие (но не все) рекурсивные алгоритмы фактически зависят от такого рода хранения (хотя версия петли обычно более эффективна в этих случаях. слишком).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top