在bst实现中传递Java参数

在bst实现中传递Java参数,java,parameter-passing,binary-search-tree,Java,Parameter Passing,Binary Search Tree,在学习了很长一段时间C之后,我又回到了Java,并且已经掌握了一个简单的概念。我开始编写一个基本的BST实现来恢复我的方向,并认为我理解Java的按值传递参数传递(是的,我理解甚至对象引用也是按值传递的,这是一个非常常见的误解) 我递归地实现了add功能,如下面的代码所示,但是我发现如果我没有实际返回节点值,它就不起作用。我已经注释掉了不起作用的行,并将它们替换为起作用的行以进行比较 我的想法是,因为对实际根节点的引用的副本被传递给add函数,所以在每个函数调用中对done的更改都是在内存中的实

在学习了很长一段时间C之后,我又回到了Java,并且已经掌握了一个简单的概念。我开始编写一个基本的BST实现来恢复我的方向,并认为我理解Java的按值传递参数传递(是的,我理解甚至对象引用也是按值传递的,这是一个非常常见的误解)

我递归地实现了add功能,如下面的代码所示,但是我发现如果我没有实际返回节点值,它就不起作用。我已经注释掉了不起作用的行,并将它们替换为起作用的行以进行比较

我的想法是,因为对实际根节点的引用的副本被传递给add函数,所以在每个函数调用中对done的更改都是在内存中的实际对象上完成的,因此如果我在左分支或右分支中添加了一个节点,它应该被保留

我感到非常尴尬,因为我知道我肯定错过了一些非常简单的东西,但阅读有关java参数传递的内容似乎让我想知道为什么我错了。谢谢你的帮助

public class BinaryTree {

    TreeNode root;

    public BinaryTree(){
        root = null;
    }

    void add(int item){
        root = add(root,item);
        //add(root,item);
    }

    //public void TreeNode add(TreeNode node, int item){
    public TreeNode add(TreeNode node, int item){
        if(node == null){
            node = new TreeNode(item);
        } else if(item <= node.getItem()){
            node.setLeft(add(node.getLeft(),item));
            //add(node.getLeft(),item);
        } else if(item > node.getItem()){
            node.setRight(add(node.getRight(),item));
            //add(node.getRight(),item);
        } 
        return node;
        //return;
    }
    static void printTree(BinaryTree tree){
        printTree(tree.root);
    }
    static void printTree(TreeNode node){
        if(node == null){
            System.out.println("Tree Empty");
            return;
        }
        if(node.getLeft() != null)
            printTree(node.getLeft());
        if(node.getRight() != null){
            System.out.print(node.getItem()+ ", ");
            printTree(node.getRight());
        } else {
            System.out.print(node.getItem()+ ", ");
        }
        return;

    }

    public static void main(String args[]){
        BinaryTree tree1 = new BinaryTree();
        tree1.add(10);
        tree1.add(3);
        tree1.add(5);
        printTree(tree1);
    }
}`
公共类二进制树{
树根;
公共二叉树(){
root=null;
}
无效添加(整数项){
根=添加(根,项);
//添加(根,项);
}
//公共void树节点添加(树节点,int项){
公共树节点添加(树节点,int项){
if(node==null){
节点=新树节点(项目);
}else if(项节点.getItem()){
setRight(添加(node.getRight(),item));
//添加(node.getRight(),item);
} 
返回节点;
//返回;
}
静态void打印树(二进制树){
printree(tree.root);
}
静态void打印树(TreeNode节点){
if(node==null){
System.out.println(“树空”);
返回;
}
if(node.getLeft()!=null)
printTree(node.getLeft());
if(node.getRight()!=null){
System.out.print(node.getItem()+“,”);
printTree(node.getRight());
}否则{
System.out.print(node.getItem()+“,”);
}
返回;
}
公共静态void main(字符串参数[]){
BinaryTree tree1=新的BinaryTree();
树1.添加(10);
树1.添加(3);
树1.添加(5);
打印树(tree1);
}
}`

这是因为在
void add
方法中,您将根设置为等于
TreeNode add
的结果,因此必须返回一些内容,否则根将为空。例如,让我们将第一个元素添加到BST。运行
TreeNode add
方法后,必须返回一些内容,因为这将在
void add
方法中,最终被分配到
root
。下面是一个如果不返回任何内容将发生的情况的摘要

void add(10) gets executed
root = add(root, 10)
TreeNode add(root, 10) gets executed
if(node == null) evaluates to true
node = new TreeNode(10); // this is where java being pass by value matters

您认为root实际上正在更改为一个新的TreeNode对象,其项值为10。但是,这并没有发生。而是每当调用一个接受参数的方法时,都会生成指向这些参数中的对象的指针。因此调用
TreeNode add(root,10)
创建一个指向
根节点的指针。该指针称为
节点
,因此,当您在最后一行中更改
节点
时,它会更改指针
节点
指向的对象,而保持
根节点
未被触及。如果您不返回
节点
,则您对新的t节点的引用不做任何操作重新定义刚创建的对象,使其在Java的垃圾收集中丢失。

如果根为null,则需要将其设置为某个值。如果传递null以添加(节点、项)您创建了一个新节点,但在返回它并对其进行处理之前,它不会被引用到函数之外的任何地方。当然!感谢我的tunnel vision!我注释掉了不起作用的行,因此在我的void add方法中,我实际上只使用了调用add(root,item)没有赋值。但是你的回答解决了问题,我没有在空根情况下对我新创建的节点做任何操作。谢谢!!