理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]

Posted

技术标签:

【中文标题】理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]【英文标题】:Understanding references in Java; addNode() function for BST is not behaving as it should [duplicate] 【发布时间】:2021-12-25 07:00:09 【问题描述】:

我试图了解为什么我的第一个实现 addToTree() 不起作用,但第二个实现。我已经评论了不同的行:

public static void addToTree(Node n, int value) //return type is void
    if (n != null)
        if (n.val >= value)
            addToTree(n.left, value);
         else  
            addToTree(n.right, value);
        
     else 
        n = new Node(value);
    

这是实际有效的实现:

public static Node addToTree(Node n, int value) //return type is Node
    if (n != null)
        if (n.val >= value)
            n.left = addToTree(n.left, value); //sets n.left with the return value
         else  
            n.right = addToTree(n.right, value); //sets n.right with the return value
        
     else 
        n = new Node(value);
        return n; //returns the new node after creating (adding) it
    
    return n;

为什么我必须将n.rightn.left 设置为addToTree() 的返回值?我不明白为什么 void 函数在这里不起作用以及为什么必须返回新节点。这是否解释了 Java 的“按值传递”性质?调用addToTree(n.left, value)时,是不是没有传递对n.left的引用?

【问题讨论】:

【参考方案1】:

简答:Java 是按值传递,而不是按引用传递

长答案:由于 Java 是按值传递的,因此在方法中传递的任何值都将首先复制到内存中的不同位置,然后将该位置传递给方法。并且当方法更改值时,新(即复制)位置的值将更改,原始副本保持不变。

在原始值的情况下,只有值被复制到新位置,但在引用类型的情况下,传递给方法的值也会被复制,但由于它们是对其他位置的引用,所以引用的位置指向的仍然是一样的。

在你的情况下,当你在下一次递归调用中传递 n.left/right 时,引用被复制到不同的位置,最后一次递归调用在那个不同的位置写了n=new Node(value);,但实际的 node.left/ right 保持不变。

当您看到引用类型作为按值传递时,我知道这一切都令人困惑。理解为什么将两个整数传递给交换方法不起作用,但传递一个包含两个元素的数组,并在 Java 中交换数组中的值。概念基本相同。查看此链接了解更多信息:Java: Why does this swap method not work?

【讨论】:

【参考方案2】:

第一个实现的问题是,您创建的新节点被分配给n,但随后n 立即超出范围并且对该节点的引用丢失。

当您声明方法参数Node n 时,您定义的变量n 类型为Node,其范围仅限于此方法。当您调用该方法并传递像addToTree( myNode, myValue ) 这样的参数时,方法内部的变量n 被分配myNode,就像分配n = myNode。在您的方法结束时,您为n 分配一个新值。这类似于做这样的事情:

Node myNode = new Node( 7 );
Node n = myNode; // Now n points to the same object as myNode
...
n = new Node( 10 ); // Now n points to a different object

您是否希望 myNode 现在的值为 10?不,因为这两个变量指向不同的对象。在您的方法中,变量n 被分配了一个带有value 的新节点,但是一旦您的方法结束,n 的范围就会结束并且对您的新节点的引用消失。

所以基本上你创建了一个新节点,然后你立即失去它。您必须从您的方法中返回该新节点,以便有人可以将其保存在树中的某个位置。在您更改的其他行中,您将该新节点保存在树中,例如n.left = addToTree( n.left, value )。这将获取方法调用的结果,该结果将是新创建的节点,并将其存储在节点 n 的左侧。

【讨论】:

以上是关于理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

java 450.删除BST中的节点(#1).java

java 450.删除BST中的节点(#1).java

java 450.删除BST中的节点(#1).java

java 450.删除BST中的节点(#1).java

java 450.删除BST中的节点(#1).java

java 450.删除BST中的节点(#1).java