递归是如何工作的

时间:2013-01-30 20:38:23

标签: c# recursion

这是我的代码

using System;
public class Program
{
   public static void Method(int flowerInVase)
      {
         if (flowerInVase > 0)
         {
             Method(flowerInVase - 1);
             Console.WriteLine(flowerInVase);
         }
      }

   public static void Main()
   {
      Method(3);
   }
}

我对行Console.WriteLine(flowerInVase);感兴趣,该方法调用自身直到它被条件终止。只有在堆栈已满之后,它才会弹出上面的每个方法,并且控制台从最少1,2,3开始写入数字。

为什么console.writeline仅在堆栈弹出时起作用,为什么不在方法写入终止的方式上写入数字,如3,2,1?编译器仅在完成递归时才使用writeline。

7 个答案:

答案 0 :(得分:9)

调用的结构如下所示。也许这种可视化将帮助您理解为什么数字打印1,2,3而不是3,2,1:

Method(3);
  flowerInVase > 0 ?
  Yes - Method(2);
    flowerInVase > 0 ?
    Yes - Method(1);
      flowerInVase > 0 ?
      Yes - Method(0);
        flowerInVase > 0 ?
        No
      WriteLine(1);
    WriteLine(2);
  WriteLine(3);

原因是,在Method(flowerInVase - 1)调用WriteLine(flowerInVase)的来电是。执行操作在有机会打印它所在的数字之前会跳转到该方法的不同副本。

答案 1 :(得分:3)

由于if语句中的行的排序方式,您获得了1,2,3。

Main()来电Method(3) Method(3)在有机会打印“3”之前调用Method(2)。执行立即跳转到Method的顶部;第一次调用Methodflowersinvase=3,在递归调用之前不会完成。同样,Method(2)会立即拨打Method(1)Method(1)会拨打Method(0)

Method(0)什么都不做,然后返回到Method(1),正好在它停止的地方;下一行是你的WriteLine电话,打印“1”然后返回,接听电话到Method(2)停止,打印“2”,依此类推“3”。

如果您调用的方法在跳转到递归调用的任何方法之前完成,那么您只会获得“3,2,1”,这不是C#的工作方式。关于方法调用你必须要记住的是,一旦你调用一个方法,执行会立即跳转到你调用的方法的开头;在方法返回之前,方法调用之后的代码将不会执行。

答案 2 :(得分:1)

  

只有在完成递归时,编译器才会使用writeline。

它是,因为你告诉它这样做。在您的代码中,首先执行递归(call Method()),并且只有在完成后,才能写入数字。

如果要在执行递归之前先编写数字,则需要在代码中切换语句:

public static void Method(int flowerInVase)
{
   if (flowerInVase > 0)
   {
       Console.WriteLine(flowerInVase);
       Method(flowerInVase - 1);
   }
}

答案 3 :(得分:1)

因为它这样做:

flowerInVase = 3
call Method(3)
    call Method(2)
        call Method(1)
        WriteLine(1)
    WriteLine(2)
WriteLine(3)

输出是:

1
2
3

如果您反转这些行:

    Console.WriteLine(flowerInVase);
    Method(flowerInVase - 1);

首先打印然后递归,所以它会打印3,2,1而不是。

答案 4 :(得分:1)

  

为什么console.writeline仅在弹出时弹出,为什么不弹出   在方法转到终止的方式上写数字,比如   3,2,1?

因为您的Method(flowerInVase - 1); Console.WriteLine(flowerInVase);之前被称为

答案 5 :(得分:0)

如果你逐行遵循代码执行,这是有道理的。如果你打破它真正的含义是你总是在你有机会向控制台写任何东西之前创建一个新的递归调用实例。只有在创建了所有允许的调用(if语句失败)后才能控制返回的线程 现有的方法。

Create method -> check parameter 
  -> create method - > check parameter
    -> create method -> check parameter
      etc. etc.
    -> print value
  -> print value
-> print value

所以现在你看到它正在以控制它的方式恢复控制。最后一个被调用的函数需要在调用它之前完成其操作。

答案 6 :(得分:0)

也许您应该调查递归的含义。这是一个递归方法的一个非常简单的例子:即一个调用自身的方法。递归在许多领域都有很多用途,尤其是编程,但这不是你问的,也不是我要回答的问题。

如果您逐行阅读代码,您会看到Method(3)被调用,而Method(2)又会调用Method(2),最重要的是,它会在输出值3之前进行此调用。所以因此,Method(3)将在输出Method(2)的最后一行之前完整执行。同样,Method(1)在输出2之前调用自身,因此整个Main() -> Method(3) --->calls Method(2) --->calls Method(1) -Method(0) not viable -if statement failed -Outputs '1' -Outputs '2' -Outputs '3' End of Main() 将在此之前执行。

一个简单的流程图:

{{1}}