删除二叉搜索树中的节点

时间:2020-02-19 13:46:06

标签: java data-structures binary-search-tree

我已经实现了以下方法来删除BST中的节点,以遵循发布于here的示例:

NodeT类

public class NodeT {
    int elem;
    NodeT left;
    NodeT right;
    public NodeT(int elem){
        this.elem=elem;
    }
}

BinaryTree类

public class BinaryTree {
    NodoT root;
    public void insertElem(int n){
        root=addRec(root,n);
    }
    public NodoT addRec(NodeT n, int elem){
        if (n==null){
            n=new NodeT(elem);
        }
        else{
            if (elem<n.elem){
                n.left=addRec(n.left,elem);
            }
            else{
                n.right=addRec(n.right,elem);
            }
        }
        return n;
    }
    public void inorder(NodeT n){
        if (n!=null){
            inorder(n.left);
            System.out.println(n.elem);
            inorden(n.right);
        }
    }

    public NodeT search(NodeT root, int n){
        if (root.elem==n) return root;
        else{
            if (n<root.elem){
                if (root.left!=null){
                    return search(root.left,n);
                }
                else return null;
            }
            else{
                if (root.right!=null){
                    return search(root.right,n);
                }
                else return null;
            }
        }
    }

    public void delete(int n){
       root=deleteNode(root,n);
    }


    public NodeT deleteNode(NodeT curr, int n){
        NodoT answ;
        answ=search(curr,n);
        if (answ==null){
            System.out.println("not found");
            return curr;
        }
        else{

            if (curr.left==null)return curr.right; 
            else if (curr.right==null) return curr.left;
            curr.elem=minValue(curr.right);
            curr.right=deleteNode(curr.right,curr.elem);
        }
        return curr;
    }


    int minValue(NodoT curr){

        int min=curr.elem;
        while (curr.left!=null){
            menor=curr.left.elem;
            curr=curr.left;
        }
        return min;
    }


//main program


BinaryTree bt=new BinaryTree();        
   int data[]={50,30,70,20,40,60,80};

    for (int i=0;i<data.length;i++){
        bt.insertElem(data[i]);
    }
    bt.inorder(bt.root);

    bt.delete(20);
    bt.inorder(bt.root);


    bt.delete(30);
    bt.inorder(bt.root);


    bt.delete(50);
    bt.inorder(bt.root);

但是,当我进行测试时,它会在第bt.delete(50);行上打印“ not found”,这是我做错了什么?

2 个答案:

答案 0 :(得分:1)

代码中有很多错误,我认为您是从您的语言转换而来的,缺少一些变量名。但是,我更正了名称并测试了代码。

问题:在您的deleteNode()中,您不会重复执行该树,即检查是否元素小于或大于curr的值。您需要再添加几条IF检查。

解决方案::用这个替换您的deleteNode()

public NodeT deleteNode(NodeT curr, int n){
    NodeT answ;
    answ=search(curr,n);
    if (answ==null){
        System.out.println("not found");
        return curr;
    }
    // need to check whether value is small or greater 
    if (n < curr.elem) 
        curr.left = deleteNode(curr.left, n); 
    else if (n > curr.elem) 
        curr.right = deleteNode(curr.right, n); 


    // if value is same, means this is the node to be deleted
    else{

        if (curr.left==null)
            return curr.right; 
        else if (curr.right==null) 
            return curr.left;
        curr.elem=minValue(curr.right);
        curr.right=deleteNode(curr.right,curr.elem);
    }
    return curr;
}

答案 1 :(得分:0)

insertElem

public void insertElem(int n){
    root=addRec(root,n);
}

每次添加一些值时,您都将覆盖root,因此在第二次插入时,您会忘记其父级,依此类推,最终您只会知道80,因为这是您插入的最后一个元素,您用来覆盖root的最后一个值。 root仅应在null时初始化,例如

if (root == null) root=addRec(root,n);

addRec

public NodoT addRec(NodeT n, int elem){
    if (n==null){
        n=new NodeT(elem);
    }
    else{
        if (elem<n.elem){
            n.left=addRec(n.left,elem);
        }
        else{
            n.right=addRec(n.right,elem);
        }
    }
    return n;
}

您总是将n.leftn.right设置为addRec返回的值,这会破坏您的结构。您可以正确地调用addRec,但是如果各自的值为n.left,则只能将其分配给n.rightnull

顺序

从我们当前的角度看,似乎无关紧要。

搜索

看起来不错。

删除

看起来不错。

deleteNode

public NodeT deleteNode(NodeT curr, int n){
    NodoT answ;
    answ=search(curr,n);
    if (answ==null){
        System.out.println("not found");
        return curr;
    }
    else{

        if (curr.left==null)return curr.right; 
        else if (curr.right==null) return curr.left;
        curr.elem=minValue(curr.right);
        curr.right=deleteNode(curr.right,curr.elem);
    }
    return curr;
}

您没有在比较实际数字。这样的想法应该是,如果值要大于当前节点的值,则将在右分支中搜索要删除的项目,否则将在左分支中进行搜索。如果您需要搜索的分支到达null,则该项目在树中不存在。请参阅Zain Arshad的实现。我本来可以做类似的事情,但是由于他已经实现了,所以我会参考并赞成它,