Java: 在方法中将对象设置为null没有任何效果(代码重用)

6

我正在尝试编写一个从二叉搜索树中删除节点的方法。以下是我的删除节点方法。

public void delete(int deletionNodeValue) {
    Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue);
    if(nodeToBeDeleted == null) return; // No node with such value exists throw an error
    if(isLeafNode(nodeToBeDeleted)) {
        nodeToBeDeleted = null;
    } else if (nodeToBeDeleted.getNumChildren() == 1) {
        bypassNode(nodeToBeDeleted);
    }else {
        replace(nodeToBeDeleted, getSuccessor(nodeToBeDeleted.getValue()));
    }
}

我在叶节点上检查了这种方法,虽然经过调试后我发现执行nodeToBeSelected=null,但该节点实际上并未被删除。因为我仍然可以搜索已删除的值,并且程序仍然能够获取它。

tree.add(5);
tree.delete(5);
System.out.println(tree.getNode(5).getValue()); // Output : 5, should've been deleted

这是我的getNode()方法。
public Node<Integer> getNode(int searchValue) {
    Node<Integer> currentNode = root;
    while(currentNode != null) {
        int currentNodeValue = currentNode.getValue();
        if(searchValue == currentNodeValue)
            return currentNode;
        else if(searchValue < currentNodeValue)
            currentNode = currentNode.getLeftChild();
        else
            currentNode = currentNode.getRightChild();
    }

    // if no node with given value is found
    return null;
}

getNode()方法返回找到的节点的值吗?我该如何使其返回引用并直接操作找到的节点?

3个回答

6

您需要从树中删除节点,而不是在程序中本地删除。

Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue);

此方法会返回树中节点的副本。

nodeToBeDeleted = null;

将此副本设置为null。树的连接不会被删除,因为它是节点对象的一部分。要删除连接,您需要编写另一个方法来删除节点,其中应包含类似以下内容的内容:

parent.leftNode = null; // if nodeToBeDeleted == leftNode
parent.rightNode = null; // if nodeToBeDeleted == rightNode

@NashVali 我认为你不应该将 leftNoderightNode 定义为 public 字段。使用 setter 是更好的选择。 - Chetan Kinger
是的,它们不应该是公共的。这段代码是一个虚构的方法 void deleteChild(Node nodeToBeDeleted) 的片段。 - CoronA
虚构的方法仍然可以使用虚构的setter而不是使用虚构的公共字段。请参见我的答案。 - Chetan Kinger

5
当你在delete方法中写下nodeToBeDeleted = null;时,你并没有真正让getNode方法返回的Node指向一个null
Java始终是按值传递的。这意味着你不能在方法内部使传递给方法的引用指向一个新的内存位置。同样地,你也不能使方法调用返回的引用指向另一个方法内部的新内存位置。(即使该位置是一个空值)。
根据上述解释,几乎不可能使用getNode方法获取想要删除的Node,然后在其他方法中使该节点指向null。一个快速的解决方案是在delete方法中复制getNode方法中的代码。你应该在Node中添加setLeftChildsetRightChild方法(而不是像其他人提出的那样将leftChild和rightChild设为public)。你可以按如下方式将其设置为空:nodeToBeDeleted.setLeftChild(null)

4
当你将nodeToBeDeleted设置为null时,你只是设置了保存实际对象引用的局部变量的值。实际对象并没有被删除。
根据你在这里展示的代码,要删除该节点,你应该找到它的父节点,并将对该节点(leftChild或rightChild)的引用设置为null。这将确保该对象不再被其父节点引用,可能不再被任何引用可见,因此可以进行垃圾回收。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接