【问题标题】:Will objects on heap be replicated on stack on function call?堆上的对象会在函数调用时复制到堆栈上吗?
【发布时间】:2014-12-17 19:56:21
【问题描述】:

在 Java 中,当调用方法时,堆上的对象会被复制到堆栈上吗?考虑这段代码 -

static void mirror(Node p){
    if (p!=null) {
        Node temp = null;
        temp = p.left;
        p.left = p.right;
        p.right = temp;

        mirror(p.left);
        mirror(p.right);
    }
}

空间复杂度会是 -

  1. O(n),因为 Node 对象 p 在每次递归调用时都被推送/复制到堆栈上
  2. O(1) 因为 Node 对象已经在内存中,而 p 只是对它的引用
  3. O(n) 因为引用 p 在方法调用时被压入堆栈

编辑:其中 n 是树的深度

【问题讨论】:

  • 2.对象不会在 Java 中隐式复制。
  • 谢谢。我很感激你的 cmets。
  • if (p == null) { return; } :-p temp= null 也是多余的,因为你直接初始化它。

标签: java recursion space-complexity


【解决方案1】:

两者都不是。

对象在将它们的引用传递给方法调用的参数时被复制,但引用本身仍然占用堆栈空间,因此空间复杂度为 O(n) 假设 n 指的是二叉树的深度。

O(…) 表示法忽略了常数比例因子,因此O(n) 仅表示每次递归都需要一定数量的堆栈空间,如果您不将任何参数传递给调用的方法,这甚至是正确的。它没有说明需要多少空间。


编辑:现在您已经编辑了问题,添加了第 3 点,现在是第 3 点,但并不完全是因为,如上所述,即使您没有将引用压入堆栈,也需要堆栈空间。


另外请记住,您必须明确n 指的是什么。如果n 是你的树的Nodes 的总数,那么如果树是平衡的,则它是O(log(n))。但是如果n 是与最大递归深度匹配的树的最大深度,那么它就是O(n)

【讨论】:

  • 让我们说一个除了调用自身并在某些条件下退出之外什么都不做的方法。当根本没有方法级别的变量时,在这种情况下是否也是如此?
  • 原则上是的,正常情况下调用者的信息会被压入栈中,以记住返回时从哪里继续操作。通常 JVM 也会支持可调试的堆栈跟踪。但是,有一些优化可能会在运行时将代码转换为非递归操作,因此这句话并不是绝对的事实。但这高度依赖于 JVM 的实现。
  • 太棒了!谢谢你的详细解答
【解决方案2】:

对象 p 不会被复制到堆上,但每次递归都会将 p 的引用放入堆栈中。

【讨论】:

    猜你喜欢
    • 2016-02-04
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2010-12-08
    • 1970-01-01
    相关资源
    最近更新 更多