简体   繁体   English

从二叉搜索树中删除节点

[英]Deleting a node from a Binary Search Tree

My Binary Search Tree program doesn't seem to be deleting anything when I call the deleteNode method. 当我调用deleteNode方法时,我的Binary Search Tree程序似乎没有删除任何内容。 The BST is built perfectly, its just deleting the node part that doesn't work. BST构建完美,仅删除了无效的节点部分。 I call it from my main like this: 我这样称呼我:

System.out.println("Please enter a number you would like to delete from the tree");
    temp = reader.nextLine();
    try {
        int numTemp = Integer.parseInt(temp);
        TreeNode treeTemp = bst.deleteNode(numTemp, bst.getRoot());
        bst.setRoot(treeTemp);
    }
    catch(Throwable e){
        System.err.println(e);
    }
    bst.printInBST(bst.getRoot());

In my BinarySearchTree class I implement my deleteNode methods as following: 在我的BinarySearchTree类中,我实现了deleteNode方法,如下所示:

public TreeNode deleteNode(int x, TreeNode temp){
    if(temp != null){
        if(x > (int)((Integer)temp.getValue())){
            temp.setLeft(deleteNode(new Integer(x), temp.getLeft()));
        }
        else if(x < (int)((Integer)temp.getValue())){
            temp.setRight(deleteNode(new Integer(x), temp.getRight()));
        }
        else if(temp.getLeft() != null & temp.getRight() != null){
            TreeNode temp2 = new TreeNode(temp.getRight().getValue());
            while(temp2.getLeft() != null){
                temp2 = temp2.getLeft();
            }
            temp = temp2;
            temp.setRight(remove(temp.getRight()));
        }
    }
    return temp;
}
public TreeNode remove(TreeNode temp){
        if(temp.getLeft() != null){
            temp.setLeft(remove(temp.getLeft()));
            return temp;
        }
        else {
            return temp.getRight();
        }
}

I think you are not handling the 我认为您没有处理

case 1: where the deleting node is a leaf node 情况1:删除节点是叶节点

case 2: where the deleting node has just 1 child 情况2:删除节点只有1个孩子


the else if part should be something like this. 否则,如果部分应该是这样的。

else if( temp.getLeft() != null && temp.getRight() != null ) // Two children
{
      temp.setValue( findMin( temp.getRight() ).getValue());
      temp.setRight ( deleteNode( temp.getValue(), temp.getRight() );
}
else
     temp = ( temp.getLeft() != null ) ? temp.getLeft() : temp.getRight();

return temp;

The findMin method is to find the inorder successor of the node to be deleted. findMin方法用于查找要删除的节点的有序后继。

private TreeNode findMin( TreeNode t )
{
        if( t == null )
            return null;
        else if( t.getLeft() == null )
            return t;
        return findMin( t.getLeft() );
}

I hope this answer your question. 我希望这能回答您的问题。

Writing legible code makes bugs easier to spot - both by yourself and others. 编写清晰的代码可以使错误更容易被发现-无论是您自己还是他人。 A first step is choosing more expressive variable names than temp , temp2 , and treeTemp . 第一步是选择比temptemp2treeTemp更富表现力的变量名。

Also, it is really not neccessary to do new Integer(x) to assign a method parameter of type int . 同样,确实不需要执行new Integer(x)来分配类型为int的方法参数。 Simply writing x instead has the same effect, is faster at runtime, and makes it easier to spot the code that matters. 只需编写x达到相同的效果,在运行时速度更快,并且更容易发现重要的代码。

As for bugs, the first one I see is: 至于错误,我看到的第一个是:

TreeNode temp2 = new TreeNode(temp.getRight().getValue());

That creates a copy of the TreeNode. 这将创建TreeNode的副本。 Changing that copy won't affect the original node. 更改该副本不会影响原始节点。 Also, the copy probably doesn't have left or right set, since you only pass the value to the constructor. 另外,副本可能没有设置leftright对齐,因为您只将value传递给了构造函数。 I wonder why think you need a copy? 我不知道为什么认为您需要一份副本? After all, you don't create one here either: 毕竟,您也不在这里创建一个:

deleteNode(new Integer(x), temp.getRight())

Next, as Sashwat points out, if the node to delete has less than 2 children, your code doesn't do anything, as none of the conditions in deleteNode matches. 接下来,正如Sashwat所指出的,如果要删除的节点的子节点少于2个,则您的代码将不执行任何操作,因为deleteNode中的条件deleteNode匹配。

  public class BSTNode {
  …

  public boolean remove(int value, BSTNode parent) {
        if (value < this.value) {
              if (left != null)
                    return left.remove(value, this);
              else
                    return false;
        } else if (value > this.value) {
              if (right != null)
                    return right.remove(value, this);
              else
                    return false;
        } else {
              if (left != null && right != null) {
                    this.value = right.minValue();
                    right.remove(this.value, this);
              } else if (parent.left == this) {
                    parent.left = (left != null) ? left : right;
              } else if (parent.right == this) {
                    parent.right = (left != null) ? left : right;
              }
              return true;
        }
  }

Not 100% sure if this is your only problem, but should: 无法100%确定这是否是您唯一的问题,但应:

else if(temp.getLeft() != null & temp.getRight() != null)

actually be: 实际上是:

else if(temp.getLeft() != null && temp.getRight() != null)

ie you only have one & for the "and" operation when you should have two? 即您只有一个&,而“ and”运算应该有两个?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM