Java 递归二叉搜索树删除
注意:我已经包含了插入的代码,以防我的错误出现 删除二进制搜索树中的节点时遇到问题。我通过eclipse运行了这个过程,节点的“指针”似乎被重新分配,但一旦我退出递归方法,它就会回到节点原来的方式 我可能误解了java是如何在方法之间传递树节点的Java 递归二叉搜索树删除,java,algorithm,recursion,tree,Java,Algorithm,Recursion,Tree,注意:我已经包含了插入的代码,以防我的错误出现 删除二进制搜索树中的节点时遇到问题。我通过eclipse运行了这个过程,节点的“指针”似乎被重新分配,但一旦我退出递归方法,它就会回到节点原来的方式 我可能误解了java是如何在方法之间传递树节点的 public abstract class BinaryTree<E> implements Iterable<E> { protected class Node<T> { protect
public abstract class BinaryTree<E> implements Iterable<E> {
protected class Node<T> {
protected Node(T data) {
this.data = data;
}
protected T data;
protected Node<T> left;
protected Node<T> right;
}
public abstract void insert(E data);
public abstract void remove(E data);
public abstract boolean search(E data);
protected Node<E> root;
}
import java.util.Iterator;
public class BinarySearchTree<E extends Comparable<? super E>> extends BinaryTree<E> {
private Node<E> findIOP(Node<E> curr) {
curr = curr.left;
while (curr.right != null) {
curr = curr.right;
}
return curr;
}
public Iterator<E> iterator() {
return null;
}
public static void remove(E data) {
if (root != null){
if (data.compareTo(root.data) == 0) {
if (root.left == null || root.right == null) {
root = root.left != null ? root.left : root.right;
} else {
Node<E> iop = findIOP(root);
E temp = root.data;
root.data = iop.data;
iop.data = temp;
if (root.left == iop) {
root.left = root.left.left;
} else {
Node<E> curr = root.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else {
if (data.compareTo(root.data) < 0) {
remove(root.left ,data);
} else {
remove(root.right ,data);
}
}
}
}
private void remove (Node<E> node, E data){
if (data.compareTo(node.data) == 0) {
if (node.left == null || node.right == null) {
if (node.left != null) {
// Problem is either here
node = node.left;
} else {
// or here
node = node.right;
}
} else {
Node<E> iop = findIOP(node);
E temp = node.data;
node.data = iop.data;
iop.data = temp;
if (node.left == iop) {
node.left = node.left.left;
} else {
Node<E> curr = node.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else {
if (data.compareTo(node.data) < 0) {
remove(node.left ,data);
} else {
remove(node.right ,data);
}
}
}
}
然后
tree.remove(8);
System.out.println(tree.root.left.right.data);
仍然是8而不是9
删除操作在根目录下进行,如果从
根。左和根。右
如有任何建议,将不胜感激
编辑:我似乎缩小了问题的范围。我实现了一个迭代版本,其中我使root=curr并更改curr.left.right=curr.left.right.right。我注意到,当我将node=root.left.right传递给递归函数将node更改为node.right时,此更改反映了根节点的更改。为什么会这样
再缩小一些。为什么node.left=node.left.left对我的树进行更改,而node=node.left什么也不做
我通过递归地重新分配父节点来修复它,而不是递归地重新分配子节点。这是由此产生的私人和公共职能
public void remove(E data) {
Node<E> curr;
if (root != null) {
if (data.compareTo(root.data) == 0) {
if (root.left == null || root.right == null) {
root = root.left != null ? root.left : root.right;
}
else {
Node<E> iop = findIOP(root);
E temp = root.data;
root.data = iop.data;
iop.data = temp;
if (root.left == iop) {
root.left = root.left.left;
}
else {
curr = root.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else if (data.compareTo(root.data) < 0) {
root.left = remove(data, root.left);
} else {
root.right = remove(data, root.right);
}
}
}
private Node<E> remove(E data, Node<E> node){
Node<E> curr;
if (node != null){
if (data.compareTo(node.data) == 0) {
if (node.left == null || node.right == null) {
node = node.left != null ? node.left : node.right;
return node;
} else {
Node<E> iop = findIOP(node);
E temp = node.data;
node.data = iop.data;
iop.data = temp;
if (node.left == iop) {
node.left = node.left.left;
return node;
} else {
curr = node.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
return node;
}
}
} else {
if (data.compareTo(node.data) < 0) {
node.left = remove(data, node.left);
if (node.left != null){
return node.left;
}
} else {
node.right = remove(data, node.right);
if (node.right != null){
return node.right;
}
}
// if node.left/right not null
return node;
}
}
// if node = null;
return node;
}
公共作废删除(E数据){
节点电流;
if(root!=null){
if(data.compareTo(root.data)==0){
if(root.left==null | | root.right==null){
root=root.left!=null?root.left:root.right;
}
否则{
节点iop=findIOP(根节点);
E temp=根数据;
root.data=iop.data;
iop.data=温度;
如果(root.left==iop){
root.left=root.left.left;
}
否则{
curr=root.left;
while(当前右侧!=iop){
curr=curr.right;
}
curr.right=curr.right.left;
}
}
}else if(data.compareTo(root.data)<0){
root.left=删除(数据,root.left);
}否则{
root.right=删除(数据,root.right);
}
}
}
删除专用节点(E数据、节点){
节点电流;
如果(节点!=null){
if(data.compareTo(node.data)==0){
if(node.left==null | | node.right==null){
node=node.left!=null?node.left:node.right;
返回节点;
}否则{
节点iop=findIOP(节点);
E temp=节点数据;
node.data=iop.data;
iop.data=温度;
if(node.left==iop){
node.left=node.left.left;
返回节点;
}否则{
curr=node.left;
while(当前右侧!=iop){
curr=curr.right;
}
curr.right=curr.right.left;
返回节点;
}
}
}否则{
if(data.compareTo(node.data)<0){
node.left=删除(数据,node.left);
if(node.left!=null){
返回node.left;
}
}否则{
node.right=删除(数据,node.right);
if(node.right!=null){
返回node.right;
}
}
//如果node.left/right不为空
返回节点;
}
}
//如果node=null;
返回节点;
}
您说的“我可能误解了java是如何在方法之间传递树节点的”,这是对的。考虑:
public class Ref {
public static void main(String args[]) {
Integer i = new Integer(4);
passByRef(i);
System.out.println(i); // Prints 4.
}
static void passByRef(Integer j) {
j = new Integer(5);
}
}
虽然i
是“通过引用传递的”,但是引用i
本身不会被方法改变,只会改变j
引用的东西。换句话说,j
是用引用i
的副本初始化的,也就是说,j
最初指的是与i
相同的对象(但关键不是i
)。指定j
引用其他内容对i
引用的内容没有影响
为了在搜索中实现您想要的,我建议您将新的引用返回给调用者。例如,类似于以下更改的内容:
public class Ref {
public static void main(String args[]) {
Integer i = new Integer(4);
i = passByRef(i);
System.out.println(i); // Prints 5.
}
static Integer passByRef(Integer j) {
j = new Integer(5);
return j;
}
}
我几乎可以肯定的问题是,当你完成任务时,你会认为这个对象实际上是复制的,而只是引用。我正试图用我目前的数据结构来解决这个问题。我也考虑过通过父节点,但我不知道父节点的移动方向。我正在尝试传递节点,并在递归传递之前对node.left和node.right进行编辑。我正在尝试类似的操作。我会告诉你事情的进展。@MateuszPejko祝你好运!谢谢,解决了。我公布了结果。我相信我可以用较少的比较来做,但我会在其他时间做。
public class Ref {
public static void main(String args[]) {
Integer i = new Integer(4);
i = passByRef(i);
System.out.println(i); // Prints 5.
}
static Integer passByRef(Integer j) {
j = new Integer(5);
return j;
}
}