我正在研究BinarySearch程序,我正在研究将值插入树中的方法。
但是,当我运行代码时,根变量的节点不会被参考变量current更改。
为什么会这样?
我的代码:
public boolean insert(E element) {
return insert(element, root);
}
private boolean insert(E element, OrderedSet<E>.TreeNode current) {
if (current == null) {
current = new TreeNode(element);
return true;
}
if (current.data.compareTo(element) == 0) {
return false;
} else {
if (current.data.compareTo(element) > 0) {
return insert(element, current);
} else {
current = current.right;
return insert(element, current);
}
}
}
答案 0 :(得分:0)
Java参数始终按值传递。当参数是引用变量时,这有点令人困惑。需要注意的是:
那么我们可以对上述计划做些什么呢?假设您有权访问TreeNode
对象的left
和right
字段,则应更改方法,以便current
参数始终代表父任何添加节点的节点。这样,它永远不会是null
,它永远是一个真实的对象。在一个真实的对象中,我们可以改变字段!
所以我们从top方法开始:
public boolean insert(E element) {
if ( root == null ) {
root = new TreeNode( element );
return true;
} else {
return insert(element, root);
}
}
如果我们树中没有任何东西 - 根是空的 - 那么我们根本不能调用我们的递归方法。就目前而言,没有“父”节点可以通过。但在这种情况下,正确的做法是将root
设置为给定元素。因此,我们使用给定元素创建一个新节点,并将其分配给root。下次root
将不再是null
!
如果它不为null,我们可以将其作为插入的“父”传递。其内容等于新元素(在这种情况下,递归方法将返回false),或者该项必须插入下的。所以这是一个很好的“父母”。
现在是递归方法本身:
private boolean insert(E element, OrderedSet<E>.TreeNode current) {
if (current.data.compareTo(element) == 0) {
// The element is already in the tree, so we do not insert
// anything, and we return false.
return false;
} else {
if (current.data.compareTo(element) > 0) {
// Smaller elements need to be inserted at the left
if ( current.left == null ) {
current.left = new TreeNode( element );
return true;
} else {
return insert(element, current.left );
}
} else {
// Bigger elements need to be inserted at the right
if ( current.right == null ) {
current.right = new TreeNode( element );
return true;
} else {
return insert(element, current.right );
}
}
}
}
现在,每种情况(更大和更小)的代码变得稍微复杂一些:
if ( current.left == null ) {
current.left = new TreeNode( element );
return true;
} else {
return insert(element, current.left );
}
我们不再允许将null
传递给下一个递归步骤,因为null
不是正确的“父”,我们将无法分配到其字段。因此,如果左分支为空,我们无法递归。但在这种情况下,适当的操作是将左节点实际设置为我们的新元素,因为它 小于当前节点。所以我们创建一个新节点,设置current.left
来引用它,现在我们已经向树中添加了一些内容,我们可以返回true
。
但是如果left
节点不为null,则它将等于给定元素,或者必须在其下的某处设置给定元素。所以左边节点是一个很好的“父”节点,我们可以用它来调用递归。
同样的逻辑也适用于向右添加元素。
因为我们要直接分配到current.left
和current.right
,这是我们给定的current
的字段,所以结果将被来电者看到。