【问题标题】:Reversing recursive java methods反转递归java方法
【发布时间】:2016-08-23 00:08:47
【问题描述】:

我正在阅读一本名为“思考 Java:如何像计算机科学家一样思考”的书,我最近介绍了递归方法。

public static void countdown(int n)
{
  if (n == 0) {
      System.out.println("Blastoff!");
  } else {
      System.out.println(n);
      countdown(n - 1);
  }
}

这将是一种用于倒数到 0 的正常递归方法,我了解发生了什么,但是如果您像这样在 System.out.println 之前进行递归调用

public static void countdown(int n)
{
  if (n == 0) {
      System.out.println("Blastoff!");
  } else {
      countdown(n - 1);
      System.out.println(n);
  }
}

它的计算方式相反,所以如果我为这两个条件语句都给出了参数 3,那么第一个参数是“3, 2, 1, Blastoff!”但是第二个 1 是“Blastoff, 1 ,2 ,3”....我不明白这是如何工作的,有人可以尝试解释这段代码中发生了什么,使它以相反的方式计数吗?

【问题讨论】:

  • 为了更好地理解它的工作原理,请将 println 作为第一个方法行。

标签: java recursion


【解决方案1】:

我会试着为你形象化。

第一种方法

countdown(3)                (first call)
"3"                         (sysout)
    countdown(3-1)          (second call)
    "2"                     (sysout)
        countdown(2-1)      (third call)
        "1"                 (sysout)
            countdown(1-1)  (fourth call)
                "Blastoff!" (n == 0)

第二种方法

countdown(3)                (first call)
    countdown(3-1)          (second call)
        countdown(2-1)      (third call)
            countdown(1-1)  (fourth call)
                "Blastoff!" (n == 0. going back up call stack)
            "1"             (sysout)
        "2"                 (sysout)
    "3"                     (sysout)

【讨论】:

    【解决方案2】:

    这样想...在第一种情况下,您总是会在执行下一个功能之前打印,所以...

    countdown(3)
      System.out.println(3)
      countdown(2)
        System.out.println(2)
        countdown(1)    
          System.out.println(1)
          countdown(0)
            System.out.println("Blastoff")
    

    结果:3 2 1 爆炸

    在第二种情况下,因为您首先打印它,所以您的运行将一直向下递归,直到基本情况开始打印......

    countdown(3)
      countdown(2)
        countdown(1)
          countdown(0)
          System.out.println("Blastoff")
        System.out.println(1)
      System.out.println(2)
    System.out.println(1)
    

    结果:1​​ 2 3 爆炸

    递归很难!我希望我能帮上忙:)

    【讨论】:

      【解决方案3】:

      这不算“相反的方式”,只是它以您可能没想到的顺序“解开”。试着写出你期望发生的事情,我很乐意帮助解决这个误解。

      【讨论】:

      • 1 秒让我把它写出来并编辑这个 WTF?为什么不保存就不能回车
      • 在第二个函数中,您的递归调用发生在println之前,因此首先达到基本情况(当n == 0 为真)。然后它返回,到达上一次调用的println 并打印3,然后返回,等等。
      • 编辑:感谢您清除它,我了解它如何调用倒计时并跳过 System.out.println,对我来说唯一奇怪的是在 n 等于 0 之后递归调用如何继续计数。
      • 因为当它返回到之前的“栈帧”时(另一位发帖人说的没错),状态又恢复到了当时的状态----n的状态不会倒退。
      【解决方案4】:

      问题是打印行将等到您的函数调用完成。因此它会在到达第一行之前连续调用函数 3 次

      【讨论】:

        【解决方案5】:

        递归的全部意义在于,每一步都有自己的“堆栈框架”和自己的局部变量,它会记住。

        因此,即使您在一次迭代中更改n,调用此迭代的函数仍将保留其自己的值n。当需要打印这个n 时,它仍然是原始值(比下一次迭代中的值大一)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-10-20
          • 1970-01-01
          • 2021-09-23
          • 1970-01-01
          • 1970-01-01
          • 2017-01-23
          • 2017-02-28
          相关资源
          最近更新 更多