Java 递归二叉搜索树删除方法
首先,这是家庭作业,所以把它放在那里 我应该用特定的方法实现一个二叉搜索树: 空插入(字符串)、布尔删除(字符串)和布尔查找(字符串) 我已经能够成功地编程和测试插入和查找方法,但在删除时遇到困难 在我的程序中,remove实际上并没有从树中删除任何内容,我相信这是因为它只引用当前节点的本地创建,但我可能错了。我想我可以实现我需要测试的不同案例的逻辑(可能需要删除一个有两个子节点的案例的帮助,但我认为我在概念上得到了它),我主要是想了解我需要做什么不同的事情,以便在Java 递归二叉搜索树删除方法,java,recursion,binary-search-tree,Java,Recursion,Binary Search Tree,首先,这是家庭作业,所以把它放在那里 我应该用特定的方法实现一个二叉搜索树: 空插入(字符串)、布尔删除(字符串)和布尔查找(字符串) 我已经能够成功地编程和测试插入和查找方法,但在删除时遇到困难 在我的程序中,remove实际上并没有从树中删除任何内容,我相信这是因为它只引用当前节点的本地创建,但我可能错了。我想我可以实现我需要测试的不同案例的逻辑(可能需要删除一个有两个子节点的案例的帮助,但我认为我在概念上得到了它),我主要是想了解我需要做什么不同的事情,以便在 current = null
current = null; // case
以下是我到目前为止得到的信息:
public boolean remove(String title)
{
return remove(root, title);
}
private boolean remove(BSTNode current, String title)
{
if (current == null)
{
return false;
}
if (current.data == title)
{
if (current.left_child !=null && current.right_child != null)
{
return true; // returning true since I haven't finished writing this case
}
else if (current.left_child == null && current.right_child == null)
{
current = null; // this should remove the node from tree but it doesn't
return true;
}
else if (current.left_child != null && current.right_child == null)
{
current = current.left_child; // don't think this is right
return true;
}
else if (current.right_child != null && current.left_child == null)
{
current = current.right_child; // not sure about this
return true;
}
}
root = current;
if (title.compareToIgnoreCase(current.data) == -1)
{
return remove(current.left_child, title);
}
else
{
return remove(current.right_child, title);
}
}
非常感谢任何知识。节点由其父节点引用(除根节点外,该节点由BST本身引用)。要从树中删除节点,需要将父节点中的引用设置为
null
您现在要做的是:
Before:
parent.left ---> node <--- current
After setting current = null:
parent.left ---> node current ---> null
By递归很烦人,因为您需要一个同时返回节点及其父节点的方法。您需要一些简单的内部类来解决此问题:
private class NodeAndParent {
public BSTNode node;
public BSTNode parent;
public NodeAndParent(BSTNode node, BSTNode parent) {
this.node = node;
this.parent = parent;
}
}
private boolean find(String title, NodeAndParent current) {
if (current.node == null) {
return false; // not found
} else {
int compare = title.compareToIgnoreCase(current.node.data);
if (compare == 0) {
return true; // found
} else {
current.parent = current.node;
if (compare < 0) {
current.node = current.node.left;
} else {
current.node = current.node.right;
}
}
}
}
private boolean remove(String title) {
NodeAndParent nodeAndParent = new NodeAndParent(root, null);
boolean found = find(title, nodeAndParent);
if (!found) {
// title was not found
} else if (nodeAndParent.parent == null) {
// found the root
} else {
// found another node
}
}
私有类节点和客户端{
公共BST节点;
公共节点父节点;
公共节点和父节点(BSTNode节点、BSTNode父节点){
this.node=节点;
this.parent=parent;
}
}
私有布尔查找(字符串标题、节点和当前不一致){
if(current.node==null){
返回false;//未找到
}否则{
int compare=title.compareToIgnoreCase(current.node.data);
如果(比较==0){
返回true;//找到
}否则{
current.parent=current.node;
如果(比较<0){
current.node=current.node.left;
}否则{
current.node=current.node.right;
}
}
}
}
私有布尔删除(字符串标题){
NodeAndParent NodeAndParent=新的NodeAndParent(根,空);
布尔查找=查找(标题、节点和属性);
如果(!找到){
//找不到标题
}else if(nodeAndParent.parent==null){
//找到根
}否则{
//找到另一个节点
}
}
非常感谢您的反馈。你所描述的就是我想象中的情况。我认为我的问题是我没有在类中定义父节点(讲师暗示这是一个不太优雅的解决方案,所以如果我们可以避免的话)。我试图了解如何在插入方法中不设置某种引用类型的情况下,告诉“当前”节点(base case=root)有关父节点的信息。我认为这样的实现是不可能的,因此我必须在插入中包含一个父节点,以跟踪哪个节点是当前节点的父节点,这样我就可以将其引用更改为null。@user2948847实际上,您不应该在每个节点中存储父节点引用,这是不必要的。请参阅我关于如何查找节点及其父节点的更新。我会选择循环版本,但如果必须使用递归,它会有点棘手。您可以通过在我称为find
的方法中执行remove来摆脱内部类,但这违反了“关注点分离”的良好实践(单个方法不应同时查找和删除节点)。
private class NodeAndParent {
public BSTNode node;
public BSTNode parent;
public NodeAndParent(BSTNode node, BSTNode parent) {
this.node = node;
this.parent = parent;
}
}
private boolean find(String title, NodeAndParent current) {
if (current.node == null) {
return false; // not found
} else {
int compare = title.compareToIgnoreCase(current.node.data);
if (compare == 0) {
return true; // found
} else {
current.parent = current.node;
if (compare < 0) {
current.node = current.node.left;
} else {
current.node = current.node.right;
}
}
}
}
private boolean remove(String title) {
NodeAndParent nodeAndParent = new NodeAndParent(root, null);
boolean found = find(title, nodeAndParent);
if (!found) {
// title was not found
} else if (nodeAndParent.parent == null) {
// found the root
} else {
// found another node
}
}