我写了两个函数,用于在树中添加一个新节点:一个公共的和一个私有的。私有的是递归的。公共的调用递归的。第一个问题:这是可以接受的做法吗?
public void addNode(int val) {
addNode(val, root, null, 0);
System.out.println("Root is null: " + (root == null));
}
private void addNode(int val, Node node, Node parent,int height) {
if(node == null) {
node = new Node(val, height, 0);
System.out.println("is new node equal to root?"+(node == root));
System.out.println("Added node on height: " + node.getHeight());
return;
}
height++;
addNode(val, node.left, node, height);
addNode(val, node.right, node, height);
}
现在问题来了:根变量没有初始化。它在树类中声明<代码>公共节点根
这让我非常困惑,因为我知道Java是按引用传递的,而不是按值传递的。为什么在调用这些函数后root为null?
控制台输出:
is new node equal to root?false
Added node on height: 0
Root is null: true
当然,从公共方法调用私有方法(甚至递归)并没有什么错。Root为null仅仅是因为您正在为节点
参数分配新值,您并没有更改对象,而是在创建新对象。
以下内容
private void addNode(int val, Node node, Node parent,int height) {
...
node = new Node(val, height, 0);
不会更改调用方中的参数节点
addNode(val, root, null, 0);
root
保持不变(使用null
值)
还要记住,在Java中,对象是按值传递的。
实际上(Java)在函数中,您只收到节点
的内存地址(值)(例如x64 arch中的000000D5098FFA70
)。因此,如果您修改例如node.left
,您实际上是在地址0000D5098FFA70 4
处更改内存。然而,如果您更改了地址值,您将失去对该对象的访问权限。从那时起,您只能使用局部变量。这就是为什么它被称为按值传递。
如果在Java代码中,一个函数为一个函数参数分配了一个新的值,这永远不会影响调用者作为参数传递的变量。您可能对参数变量发生变化时会发生什么感到困惑:例如,如果它是一个对象,并且您为它的一个属性指定了不同的值,那么调用方的对象就可以看到这种变化,因为它实际上是同一个对象。但对参数的简单赋值总是只对局部变量有影响。
为了让它工作,设计你的函数来返回你提供给它的节点(不管它是否有新的值)。
还有另一个问题:您当前正在左子树和右子树(如果存在)中添加一个新节点,这会递归重复。我假设您试图在二叉搜索树中插入值,因此您应该选择在哪个子树中添加节点。
最后,不需要将父母节点
或高度
作为参数传递,因为您似乎将高度存储在每个节点中,因此您知道新节点的高度必须比其父节点中存储的高度多一个(或者,如果不存在,则为0)。
public void addNode(int val) {
root = addNode(val, root);
}
private void addNode(int val, Node node) {
if (node == null) {
return new Node(val, 0, 0); // NB: height will be updated when backtracking
}
if (val < node.val) {
node.left = addNode(val, node.left);
node.left.height = node.height + 1;
} else {
node.right = addNode(val, node.right);
node.right.height = node.height + 1;
}
return node;
}
最后,这里的名称“height”有点误导,因为这个术语应该表示节点为根的(子)树的高度。但此代码中的height
表示节点在树中的深度。看看树的深度和高度有什么区别?。
我正在将XML返回到一个jsp页面。 最终的XML结构如下所示: 的根节点作为向量返回,我使用xtream将其别名为“tasks”,如上图所示。 如何使用XStream实现这一点?我需要使用XSLT文件来转换XML输出吗?完成这一点的最佳方法是什么?
我有一个XML: 我想向根元素:/doc添加一个属性(名称空间),以便输出如下所示: 我尝试了三种xslt(跳过了默认的“复制所有”部分以减少问题的长度)。 xslt1:见下文,问题在于将空名称空间xmlns=”“添加到/doc的所有子节点(即:/doc/tag1和/doc/tag2) Xslt2:见下文,问题是“ns”被添加到根节点:和 xslt3:请参见下文,问题是报告了错误:未定义名称空间前
为什么x没有在下面初始化? 平均而言,对于一半的迭代,for循环中的将是,从而初始化。对于另一半,找到的 循环替换为 同样糟糕。只有
问题内容: 我当时正在编写一个简短的脚本来更改元素的内部文本,但是发现它没有方法。我知道那不是继承自,但似乎不是一种有用的方法吗?是否有一个具体的实施问题,我不知道阻止添加的到? 注意:我知道Dojo和jQuery 的节点列表都有某种形式。由于限制,我无法使用任何一个。 问题答案: 现在,NodeList在所有主要浏览器中都具有forEach() 原始答案 这些答案都不能解释 为什么 NodeLi
我正在做一个项目,以创建一个超过2个子节点的树。我明白在创建二叉树时,我们可以只创建一个左节点和一个右节点来充当子节点,但当我在网上寻找创建树的帮助时,我找到的每一个解决方案都谈到了创建二叉树。我明白创建树的部分意味着您需要创建子节点数组或arraylist,但我不明白如何将数据放入数组,或者如何将子节点数组“连接”到父节点? 这是我目前掌握的代码。我知道这不是很多,但我正在努力刚刚开始这个项目。
如果我有一个struct Foo和一个struct Bar: 如果我初始化一个条并打印正确得到的值: 但是现在如果我声明这样的构造函数: 我失去了Bar::foo的默认构造,程序输出了32764 0 5! 为什么我不得不像这样无声地初始化每个成员变量: 只要我声明一个构造函数?在这种情况下,为什么默认构造不起作用?