为什么我的Java二进制搜索树类在我告诉它时实际上没有删除节点?
我正在用Java构建一个二叉搜索树,以便更好地理解它们是如何工作的,我正在开发一个函数来删除一个具有特定值的节点 我基本上是遍历树,直到找到具有正确值的节点,然后根据它有多少子节点来执行相应的操作 如果它没有子项,我将其设置为null。如果它有一个,我就把它自己和这个孩子一样。如果它有两个,我会遍历左边的树,沿着左边一直走到左边,然后删除它,并将我所在节点的值设置为已删除节点的值为什么我的Java二进制搜索树类在我告诉它时实际上没有删除节点?,java,recursion,tree,binary-tree,Java,Recursion,Tree,Binary Tree,我正在用Java构建一个二叉搜索树,以便更好地理解它们是如何工作的,我正在开发一个函数来删除一个具有特定值的节点 我基本上是遍历树,直到找到具有正确值的节点,然后根据它有多少子节点来执行相应的操作 如果它没有子项,我将其设置为null。如果它有一个,我就把它自己和这个孩子一样。如果它有两个,我会遍历左边的树,沿着左边一直走到左边,然后删除它,并将我所在节点的值设置为已删除节点的值 class BTree { public int data; public BTree leftTr
class BTree {
public int data;
public BTree leftTree;
public BTree rightTree;
public BTree(int data) {
this.data = data;
}
public BTree(int data, BTree leftTree, BTree rightTree) {
this.data = data;
this.leftTree = leftTree;
this.rightTree = rightTree;
}
public void insert(int data) {
if (data < this.data) {
if (this.leftTree == null) {
BTree newTree = new BTree(data);
this.leftTree = newTree;
} else {
insert(this.leftTree, data);
}
} else {
if (this.rightTree == null) {
BTree newTree = new BTree(data);
this.rightTree = newTree;
} else {
insert(this.rightTree, data);
}
}
}
private void insert(BTree tree, int data) {
if (tree.data == data) {
return;
}
if (data < tree.data) {
if (tree.leftTree == null) {
BTree newTree = new BTree(data);
tree.leftTree = newTree;
} else {
insert(tree.leftTree, data);
}
} else {
if (tree.rightTree == null) {
BTree newTree = new BTree(data);
tree.rightTree = newTree;
} else {
insert(tree.rightTree, data);
}
}
}
public void inorderTraversal(BTree tree) {
if (tree.leftTree != null) {
inorderTraversal(tree.leftTree);
}
System.out.print(tree.data + ", ");
if (tree.rightTree != null) {
inorderTraversal(tree.rightTree);
}
}
public void remove(int data, BTree tree) {
if (tree == null) {
return;
}
if (data == tree.data) {
if (tree.leftTree != null && tree.rightTree != null) {
int minimumValue = getMinimumValue(tree.leftTree);
remove(minimumValue, tree);
tree.data = minimumValue;
} else if (tree.leftTree != null) {
tree = tree.leftTree;
} else if (tree.rightTree != null) {
tree = tree.rightTree;
} else {
tree = null;
}
} else if (data < tree.data) {
remove(data, tree.leftTree);
} else {
remove(data, tree.rightTree);
}
}
public int getMinimumValue(BTree tree) {
if (tree.leftTree == null) {
return tree.data;
} else {
return getMinimumValue(tree.leftTree);
}
}
public static void main(String[] args) {
BTree myTree = new BTree(5);
myTree.insert(6);
myTree.insert(12);
myTree.insert(4);
myTree.insert(3);
myTree.insert(6);
myTree.insert(15);
myTree.insert(1);
myTree.insert(9);
myTree.insert(-2);
myTree.remove(3, myTree);
myTree.inorderTraversal(myTree);
}
}
类BTree{
公共int数据;
公共b树左树;
公共树;
公共BTree(int数据){
这个数据=数据;
}
公共BTree(int数据、BTree leftTree、BTree rightTree){
这个数据=数据;
this.leftTree=leftTree;
this.rightree=rightree;
}
公共空白插入(整型数据){
如果(数据<此数据){
if(this.leftTree==null){
BTree newTree=新的BTree(数据);
this.leftTree=newTree;
}否则{
插入(this.leftTree,data);
}
}否则{
if(this.rightree==null){
BTree newTree=新的BTree(数据);
this.rightree=newTree;
}否则{
插入(this.rightree,data);
}
}
}
私有void插入(BTree树,int数据){
if(tree.data==数据){
返回;
}
if(数据<树数据){
if(tree.leftTree==null){
BTree newTree=新的BTree(数据);
tree.leftTree=newTree;
}否则{
插入(tree.leftTree,数据);
}
}否则{
if(tree.rightree==null){
BTree newTree=新的BTree(数据);
tree.rightree=newTree;
}否则{
插入(tree.rightree,数据);
}
}
}
OrderTraversal中的公共无效(B树){
if(tree.leftTree!=null){
inorderTraversal(tree.leftTree);
}
系统输出打印(tree.data+“,”);
如果(tree.rightree!=null){
inorderTraversal(tree.rightree);
}
}
删除公共void(int数据,BTree树){
if(tree==null){
返回;
}
if(data==tree.data){
if(tree.leftTree!=null&&tree.rightree!=null){
int minimumValue=getMinimumValue(tree.leftTree);
移除(最小值,树);
tree.data=最小值;
}else if(tree.leftTree!=null){
tree=tree.leftTree;
}else if(tree.rightree!=null){
tree=tree.rightTree;
}否则{
tree=null;
}
}else if(数据<树数据){
删除(数据,tree.leftTree);
}否则{
删除(数据,tree.rightree);
}
}
公共int getMinimumValue(BTree树){
if(tree.leftTree==null){
返回树数据;
}否则{
返回getMinimumValue(tree.leftTree);
}
}
公共静态void main(字符串[]args){
BTree myTree=新的BTree(5);
myTree.insert(6);
myTree.insert(12);
myTree.insert(4);
myTree.insert(3);
myTree.insert(6);
myTree.insert(15);
myTree.insert(1);
myTree.insert(9);
myTree.insert(-2);
移除(3,myTree);
myTree.inorderTraversal(myTree);
}
}
尽管如此,3仍然显示在顺序遍历中。我做错了什么?以这一行为例:
tree = tree.leftTree;
您正试图通过为树
指定一个新值来重写树
但是tree
是一个方法参数。通过在方法内部重新分配它,您并不是在方法调用点重新分配方法参数:方法参数是按值传递的,始终是。这意味着引用类型参数通过值传递,作为引用的值。方法中对该值(引用)的更改在原始调用站点上没有影响。对该引用类型的内容所做的更改将产生影响
值得引用Java教程>将信息传递给方法或构造函数>
引用数据类型参数(如对象)也通过值传递到方法。这意味着当方法返回时,传入的引用仍然引用与以前相同的对象。但是,可以在方法中更改对象字段的值
看看这个简单的例子:
public static void main(String[] args) {
A a1 = new A();
System.out.println("before the method : " + a1);
reassignFail(a1);
System.out.println("after the method : " + a1);
}
static void reassignFail(A a1) {
A a2 = new A();
System.out.println("inside the method a2 : " + a2);
a1 = a2;
System.out.println("inside the method for parameter a1: " + a1);
}
static class A{
int id;
private static int iid;
public A() { id = ++iid; }
public String toString() { return "this is instance " + id; }
}
这张照片是:
before the method : this is instance 1
inside the method a2 : this is instance 2
inside the method for parameter a1: this is instance 2
after the method : this is instance 1
在方法之前:这是实例1
在方法a2内部:这是实例2
参数a1的方法内部:这是实例2
在方法之后:这是实例1
因此,您的重新分配对树结构没有影响。您的第二次插入在我看来很奇怪,因为您只需要创建一个包含数据的新BTree,或者只需要使用您已经插入的相同插入来处理所有可能的情况。inOrderTraversal也是如此 对于remove,您需要返回一个BTree,以处理“this”引用就是您想要删除的引用的情况(您不能附加到“this”)
类BTree{
公共int数据;
公共b树左树;
公共树;
公共BTree(int数据){
这个数据=数据;
}
公共BTree(int数据、BTree leftTree、BTree rightTree){
这个数据=数据;
this.leftTree=leftTree;
this.rightree=rightree;
}
公共空白插入(整型数据){
if(this.data==数据){
返回;
class BTree {
public int data;
public BTree leftTree;
public BTree rightTree;
public BTree(int data) {
this.data = data;
}
public BTree(int data, BTree leftTree, BTree rightTree) {
this.data = data;
this.leftTree = leftTree;
this.rightTree = rightTree;
}
public void insert(int data) {
if (this.data == data) {
return;
}
if (data < this.data) {
if (leftTree == null) {
leftTree = new BTree(data);
} else {
leftTree.insert(data);
}
} else {
if (this.rightTree == null) {
rightTree = new BTree(data);
} else {
rightTree.insert(data);
}
}
}
public void inOrderTraversal() {
if (leftTree != null) {
leftTree.inOrderTraversal();
}
System.out.print(data + ", ");
if (rightTree != null) {
rightTree.inOrderTraversal();
}
}
//the void equivalents are in comments
public BTree remove(int data) {
if (data == this.data) {
if (leftTree != null && rightTree != null) {
//this is the only legal case for the void remove.
int minValue = getMinimumValue();
this.data = minValue;
//leftTree.remove(minValue); //and no return is needed
leftTree = leftTree.remove(minValue);
return this;
} else if (leftTree != null) {
//this = leftTree; //illegal
return leftTree;
} else if (rightTree != null) {
//this = rightTree; //illegal
return rightTree;
} else {
//this = null; //illegal
return null;
}
} else if (data < this.data) {
leftTree = leftTree.remove(data);
return this;
} else {
rightTree = rightTree.remove(data);
return this;
}
}
public int getMinimumValue() {
if (leftTree == null) {
return data;
} else {
return leftTree.getMinimumValue();
}
}
public static void main(String[] args) {
BTree myTree = new BTree(5);
myTree.insert(6);
myTree.insert(12);
myTree.insert(4);
myTree.insert(3);
myTree.insert(6);
myTree.insert(15);
myTree.insert(1);
myTree.insert(9);
myTree.insert(-2);
myTree = myTree.remove(3);
myTree.inOrderTraversal();
}
}