从二进制搜索树中删除节点

时间:2011-10-08 17:52:46

标签: java binary-search-tree

当我调用deleteNode方法时,我的二进制搜索树程序似乎没有删除任何内容。 BST完美构建,只是删除不起作用的节点部分。我从我的主人这样称呼它:

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());

在我的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();
        }
}

4 个答案:

答案 0 :(得分:2)

我认为你没有处理

情况1:删除节点是叶子节点

案例2:删除节点只有1个孩子


其他如果部分应该是这样的。

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;

findMin方法是查找要删除的节点的inorder后继。

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

我希望这能回答你的问题。

答案 1 :(得分:1)

编写清晰的代码可以让您更容易发现错误 - 无论是您自己还是其他人。第一步是选择比temptemp2treeTemp更具表现力的变量名称。

此外,执行new Integer(x)来分配类型int的方法参数实际上并不是必需的。简单地编写x具有相同的效果,在运行时更快,并且更容易发现重要的代码。

至于错误,我看到的第一个是:

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

创建TreeNode的副本。更改该副本不会影响原始节点。此外,副本可能没有设置leftright,因为您只将value传递给构造函数。我想知道为什么你认为你需要一份副本?毕竟,你不在这里创建一个:

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

接下来,正如Sashwat指出的那样,如果要删除的节点少于2个子节点,则代码不会执行任何操作,因为deleteNode中的所有条件都不匹配。

答案 2 :(得分:0)

不是100%确定这是否是您唯一的问题,但应该:

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

实际上是:

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

即。你只有一个&amp;当你应该有两个“和”操作时?

答案 3 :(得分:0)

  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;
        }
  }