1

目前正在从事递归实践/实现,并注意到一些与我所知道的编程中正确的一切背道而驰的东西。

递归方法

protected int getArea() {

    if(width <= 0)
        return 0;
    else if(width == 1)
        return 1;
    else {

        Triangle t2 = new Triangle(width - 1);
        int area = t2.getArea();//Area variable somehow is holding the values of previous calls, despite being instantiated in each new call?

        return area + width;

    }

}

不知何故,局部变量 ,area正在聚合递归方法中先前调用的值。这怎么可能,每次调用都会实例化它?在每次调用中,似乎getArea()再次调用了该方法,area由于getArea()调用发生方法return语句之前,因此该变量无法保存任何内容。

这是怎么回事?

4

3 回答 3

4

每个方法调用的详细信息都存储在堆栈中,一旦从方法调用返回值,则执行返回到调用当前方法的上一个方法,局部变量值等。将存储在堆栈中,这就是程序需要时在执行中使用这些值的方式。围绕递归程序进行一些实验以了解更多信息。

我的建议是尝试在 Eclipse 或 Intellij 等 IDE 上使用断点调试递归程序,这样可以消除很多混乱,并清楚地说明递归的工作原理。

于 2018-11-10T07:03:28.567 回答
1

我认为你看错了。如果调用两种方法。例如。

public int test() {
    int x = getSomeInt(1);
    int y = getSomeInt(2);
    return x + y;
}

您是否曾经质疑是否return x + y已完成或x之前是否已确定的值y?它从上到下进行,并且语句设置在返回y之前未开始getSomeInt(1),其值设置为x. 所以对于你的例子:

protected int getArea() {
    if (width <= 0) {
        return 0;
    } elseif (width == 1) {
        return 1;
    } else {
        Triangle t2 = new Triangle(width - 1);
        int area = t2.getArea();
        return area + width;
    }
}

因此,如果您有一个带宽度的三角形1并给getArea1回电。

如果你在一个有宽度的三角形上做会发生什么2?好吧,它创建t2了宽度1并调用getArea它。我们已经知道结果,因为我们已经计算过了。area变成1然后它返回1 + 2

如果你用宽度 3 来做会发生什么?它将创建t2宽度2并调用getArea()它。我们知道3从上面返回,结果是3 + 3

recusive 方法被调用 high with,但它是1首先确定的方法,然后是 2, 3, 4, ...最后你实际调用的调用有一些area它添加with到。

对方法的每次调用都与被调用者无关。它是相同的代码,是的,但它是一个不同的对象,并且局部变量对于调用来说是唯一的,就像这两个调用getSomeInt也有两个不同版本的第一个参数一样。除非您正在变异或通过引用传递,否则它们不会纠缠在一起。

调用对象的方法与调用中作为参数的对象非常相似。递归调用有一个较小的对象,width并且在某一时刻它将达到基本情况。你可以说这是一样的:

public static int getArea(Triangle t) {
    if (t.width <= 0) {
        return 0;
    } elseif (t.width == 1) {
        return 1;
    } else {
        Triangle t2 = new Triangle(t.width - 1);
        int area = getArea(t2);
        return area + t.width;
    }
}

再一次.. 递归的方法不会改变任何东西。它没有特殊处理。它需要在返回值之前完成它的调用,就像你使用不同的方法来获取区域getArea一样。完全没有区别。

于 2018-11-10T14:51:06.253 回答
1

当谈到递归时,我经常发现记住你所给予的就是你得到的是很有帮助的,这意味着当你调用你的递归方法时你得到的就是决定从中返回的任何东西。

在这种情况下,你写的时候得到什么

int area = t2.getArea();

0,1area + width.

最后一种情况是递归情况,您递归地定义一个新的 Triangle 实例,新的宽度减 1,然后调用.getArea()它。这在功能上等同于定义.getArea()

protected int getArea(int width) {

    if(width <= 0)
        return 0;
    else if(width == 1)
        return 1;
    else {
        int area = getArea(width - 1);
        return area + width;
    }

}

无论您是.getArea()Triangle. 重要的是width在调用它时定义的内容(在这种情况下width - 1)以及您如何定义它对返回值的影响。

于 2018-11-10T08:09:27.070 回答