C#中的混淆递归

时间:2017-06-26 16:02:28

标签: c# recursion

作为初学者,我对以下C#递归的运行方式感到很困惑。

class program
{
    public void Count(int inVal)
    {
        if(inVal == 0)
           return;
        Count(inVal - 1);
        Console.WriteLine("{0}",inVal);
    }

    static void Main()
    {
        Program pr = new program;
        pr.Count(3);
    }
}

从我的观点来看,该计划'什么时候应该停止' intVal'达到0,因为流不能通过' if(intVal == 0)return;'。如何打印出来' 1 2 3'顺序?如果有人知道他们之间的原则,我将不胜感激。

3 个答案:

答案 0 :(得分:3)

现在你的结构方式是,在打印出你在该级别的值之前递归调用Count(),所以你的程序流程如下:

Main
  --> Count(3)
    --> Count(2)
      --> Count(1)
        --> Count(0) //here, the program returns because of your if
      --> //prints 1
    --> //prints 2
  --> //prints 3

希望这能够显示当前程序的运行方式,并有助于处理它为什么按顺序打印出值。问题是递归调用后的代码仅在递归调用完成后执行 - 对于Count(3),这意味着Count(2), Count(1),Count(0)都发生在Count(3)中的print语句之前

答案 1 :(得分:2)

我记得也对递归感到困惑,所以让我们看看能解释会发生什么。

  1. 你用3打电话给Count
    1. 计数检查3 == 0,并得到假,因此返回
    2. 然后用2(3-1)调用自己
      1. 计数检查2 == 0,并得到假
      2. 然后用1(2-1)调用自己
        1. 计数检查1 == 0,并获得错误
        2. 然后用0(1-1)调用自己
          1. 计数检查0 == 0,并且变为true,因此返回
        3. 现在计数打印1
        4. 我们现在退出方法的底部,返回上一个调用堆栈
      3. 现在计数打印2
      4. 我们现在退出方法的底部,返回上一个调用堆栈
    3. 现在计数打印3
    4. 我们现在退出方法的底部,返回上一个调用堆栈
  2. 你回到Main

答案 2 :(得分:1)

在代码运行时跟随堆栈跟踪。请注意,在调用递归Count()方法之后,之前不会打印。

如果没有图形,堆栈很难可视化,但是:

...Count(3)
  ... Count(2)
     ... Count(1)
       ... Count(0)
     ... ResumeCount(1)
  ... ResumeCount(2)
... ResumeCount(3)

每次再次调用Count时,当前方法的处理将停止,直到后续调用返回。

流程如下所示:

  1. 从主程序接收对Count的调用,值为3
  2. 检查值是否为0
  3. 再次运行Count,将值传递给2(我们现在已经将另一个Count()方法添加到堆栈中......原始的方法正在等待此返回)
  4. 检查值是否为0
  5. 再次运行Count,传递值为1
  6. 检查值是否为0
  7. 再次运行Count(),传递值为0
  8. 检查值是否为0
  9. 值**为* 0,从此返回
  10. 回到方法的先前实例(#7停止的地方)
  11. 打印1
  12. 返回并回退到前一个实例(其中#5停止)
  13. 打印2
  14. 返回和退回或之前(原始)实例(其中#3停止)
  15. 打印3
  16. 在调试器中走一遍,你会看到......

    如果您在Count调用之前移动ConsoleWriteLine调用,那么您将拥有3,2,1而不是1,2,3