我有简单的二叉搜索树类,其实例变量类型为Node,它是根。这并不复杂,只是您之前看到的与Node类相同的基本BST类,其中包含数据类型的字段和对左右节点的两个引用。我想要一个清除树的方法。最初,我想,好吧,这是:
void clearTree() { root = null; }
但是我的教授声称这并没有真正从内存中清除树,因为仍然有来自树中父节点的节点的引用......即使我们没有对它们的引用。这样说是对的吗?如果是,为什么这不能从记忆中清除树?我以为一旦我们失去对它的引用,它就会被垃圾收集。
答案 0 :(得分:3)
您无法再访问的任何内容(通过代码中的任何引用/指针)都有资格进行垃圾回收。
因此,假设您没有保留对除根节点引用之外的任何其他节点的任何引用,那么在您将根引用置空时,整个树都将启动GC。
如果你真的想向你的教授证明这一点,我建议你得到eclipse memory analyzer的副本,在将字段归零后立即拍摄快照(使用与jdk捆绑在一起的hprof命令行实用程序,让你的代码睡20秒,这样很容易捕获)然后你可以证明内存中没有强可达的节点
答案 1 :(得分:3)
你的教授是正确的,使root等于null将不会释放整个树。在像C这样的语言中,如果你使root=null
整个树仍在内存中。
但是在Java中,正如@radai所说,一旦你没有对树节点的更多引用,垃圾收集器就会为你清理它。因此,在Java上下文中,make root=null
将起作用。
无论如何,如果你确实需要清理树的每个单个节点(例如,C / C ++语言中需要什么),你可以使用pos-order算法。当然,您需要使算法适应您的变量名称和结构(或类,如果您想在Java中应用它)。
void clearTree(treenode *node) {
if (node != NULL) {
clearTree( node->leftChild );
clearTree( node->rightChild );
delete( node ); // Or in Java, node = null;
}
}
答案 2 :(得分:0)
我认为你的教授可能错了。考虑一个复合对象A
:
class A {
private B b;
private C c;
public A(B b, C c){
this.b = b;
this.c = c;
}
}
我们将其用作:
A a = new A(new B(), new C());
当你这样做时:
a = null;
a
引用的对象将被垃圾收集,并与对象的任何其他部分一起使用(如果它们未在其他地方引用)。这种情况一直在发生,我们甚至都没想过。
我相信这棵树也是一样的。它将以递归方式声称其他对象无法到达。如果没有其他对该根的引用。
修改强>
显示GC如何判断对象是否可访问的gif:here