c# - 避免递归

标签 c# recursion

我有一些代码在其实现中使用了递归。 profiler which I'm using递归函数调用效果不佳,所以我想将其重写为非递归。

目前的代码是这样的:

void Parse(Foo foo)
{
  A()
  for (;;)
  {
    B();
    if (C())
      return;
    if (D())
    {
      Run();
    }
    E();
  }
}

void Run()
{
  X();
  if (Y())
  {
    Parse();
  }
  Z();
}

以上是伪代码。字母 A、B、C、D、E、X、Y 和 Z 是方法,Parse() 和 Run() 也是。为简单起见,我省略了各种参数和对象取消引用(例如,Run 是对象实例的一种方法,它需要一些参数)。

无论如何,我的问题是,如何将其转换为非递归代码?

在我看来等效的非递归代码是:

void Parse(Foo foo)
{
  //create a local stack variable to emulate recursion
  Stack<Foo> foos = new Stack<Foo>();
  foos.Add(foo());
start_subroutine:
  A()
  for (;;)
  {
    B();
    if (C())
    {
      //instead of returning from a recursive call
      if (foos.Count > 1)
      {
        foo = foos.Pop();
        goto end_subroutine;
      }
      return;
    }
    if (D())
    {
      //instead of invoking Run as a subroutine, bring its functionality inline
      //Run();
      X();
      if (Y())
      {
        //instead of calling self recursively
        //Parse();
        //push onto a local stack variable and jump
        foos.Add(foo);
        goto start_subroutine;
      }
end_subroutine:
      Z();
    }
    E();
  }
}

我可以这样做,但是如果不使用 goto,我不知道该怎么做;而且我不记得曾经看到有人写过这是需要 goto 的情况之一。

最佳答案

我认为您走在正确的轨道上!在这种情况下,我没有看到使用 goto 有任何实际问题。代码中发生的事情真的非常清楚,人们试图避免直接跳转的唯一原因是它在阅读别人的代码时会导致混淆。

如果您将其结构保持得井井有条,并将大部分实现代码放在其他函数中,那么这看起来完全合理。特别是因为您只使用非递归代码进行分析:)

祝你好运,但你最终会继续前进!

关于c# - 避免递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1220000/

相关文章:

c# - 扩展 Enumerable.Range

c# - 键值对的有序列表?

javascript - 在javascript es6中将嵌套对象转换为递归数组或嵌套数组

python - 递归查找n维数组的相邻坐标

sql-server - 使用 SQL 获取父/子数据库中每个 ID 的相关数据

java - 使用递归方法通过控制流中断 Java 循环的迭代

python - 递归地将立方体分解为 8 个更小的立方体(当立方体由中点和大小定义时)

c# - 使用c#在excel中启用迭代计算模式?

c# - C# 中的枚举使用负数的负面影响

c# - 从控制台在新线程上创建表单