Remove method binary search tree

2019-04-11 15:51发布

问题:

I am trying to implement a remove method for the BST structure that I have been working on. Here is the code with find, insert, and remove methods:

public class BST {
    BSTNode root = new BSTNode("root");

    public void insert(BSTNode root, String title){
        if(root.title!=null){

            if(title==root.title){
                //return already in the catalog
            }
            else if(title.compareTo(root.title)<0){

                if(root.leftChild==null){
                    root.leftChild = new BSTNode(title);
                }
                else{
                    insert(root.leftChild,title);
                }
            }
            else if(title.compareTo(root.title)>0){
                if(root.rightChild==null){
                    root.rightChild = new BSTNode(title);
                }
                else{
                    insert(root.rightChild,title);
                }
            }
        }
    }

    public void find(BSTNode root, String title){
        if(root!= null){
            if(title==root.title){
                //return(true);
            }
            else if(title.compareTo(root.title)<0){
                find(root.leftChild, title);
            }
            else{
                find(root.rightChild, title);
            }
        }
        else{
            //return false;
        }
    }

    public void remove(BSTNode root, String title){
        if(root==null){
            return false;
        }
        if(title==root.title){
            if(root.leftChild==null){
                root = root.rightChild;
            }
            else if(root.rightChild==null){
                root = root.leftChild;
            }
            else{
                //code if 2 chlidren remove
            }
        }
        else if(title.compareTo(root.title)<0){
            remove(root.leftChild, title);
        }
        else{
            remove(root.rightChild, title);
        }
    }
}

I was told that I could use the insert method to help me with the remove method, but I am just not seeing how I can grab the smallest/largest element, and then replace the one I am deleting with that value, then recursively delete the node that I took the replacement value, while still maintaining O(logn) complexity. Anyone have any ideas or blatant holes I missed, or anything else helpful as I bang my head about this issue?

EDIT: I used the answers ideas to come up with this, which I believe will work but I'm getting an error that my methods (not just the remove) must return Strings, here is what the code looks like, I thought that's the return statements??

public String remove(BSTNode root, String title){
            if(root==null){
                return("empty root");
            }
            if(title==root.title){
                    if(root.leftChild==null){
                            if(root.rightChild==null){
                                    root.title = null;
                                    return(title+ "was removed");
                            }
                            else{
                            root = root.rightChild;
                            return(title+ "was removed");
                            }
                    }
                    else if(root.rightChild==null){
                            root = root.leftChild;
                            return(title+ "was removed");
                    }
                    else{
                            String minTitle = minTitle(root);
                            root.title = minTitle;
                            remove(root.leftChild,minTitle);
                            return(title+ "was removed");
                    }
            }
            else if(title.compareTo(root.title)<0){
                    remove(root.leftChild, title);
            }
            else{
                    remove(root.rightChild, title);
            }
    }

回答1:

public void remove (String key, BSTNode pos)
    {
        if (pos == null) return;
        if (key.compareTo(pos.key)<0)
            remove (key, pos.leftChild);
        else if (key.compareTo(pos.key)>0)
            remove (key, pos.rightChild);
        else {
            if (pos.leftChild != null && pos.rightChild != null)
            {
                /* pos has two children */
                BSTNode maxFromLeft = findMax (pos.leftChild); //need to make a findMax helper 
                //"Replacing "  pos.key " with " maxFromLeft.key
                pos.key = maxFromLeft.key;
                remove (maxFromLeft.key, pos.leftChild);
            }
            else if(pos.leftChild != null) {
                /* node pointed by pos has at most one child */
                BSTNode trash = pos;
                //"Promoting " pos.leftChild.key " to replace " pos.key
                pos = pos.leftChild;
                trash = null;
            }
            else if(pos.rightChild != null) {
                /* node pointed by pos has at most one child */
                BSTNode trash = pos;
                /* "Promoting " pos.rightChild.key" to replace " pos.key */
                pos = pos.rightChild;
                trash = null;
            }
            else {
                pos = null;
            }
        }
    }

This is the remove for an unbalanced tree. I had the code in C++ so I have quickly translated. There may be some minor mistakes though. Does the tree you are coding have to be balanced? I also have the balanced remove if need be. I wasn't quite sure based on the wording of your question. Also make sure you add a private helper function for findMax()



回答2:

void deleteTreeNode(int data){
    root = deleteTreeNode(root ,data);
}

private TreeNode deleteTreeNode(TreeNode root, int data) {
    TreeNode cur = root;
    if(cur == null){
        return cur;
    }
    if(cur.data > data){            
        cur.left = deleteTreeNode(cur.left, data);
    }else if(cur.data < data){
        cur.right = deleteTreeNode(cur.right, data);
    }else{          
        if(cur.left == null && cur.right == null){
            cur = null;
        }else if(cur.right == null){
            cur = cur.left;
        }else if(cur.left == null){
            cur = cur.right;
        }else{
            TreeNode temp  = findMinFromRight(cur.right);
            cur.data = temp.data;
            cur.right = deleteTreeNode(cur.right, temp.data);
        }
    }
    return cur;
}

private TreeNode findMinFromRight(TreeNode node) {
    while(node.left != null){
        node = node.left;
    }
    return node;
}


回答3:

To compare objects in java use .equals() method instead of "==" operator

  if(title==root.title)
          ^______see here

you need to use like this

 if(title.equals(root.title)) 

or if you are interesed to ignore the case follow below code

 if(title.equalsIgnoreCase(root.title))


回答4:

private void deleteNode(Node temp, int n) {
    if (temp == null)
        return;
    if (temp.number == n) {
        if (temp.left == null || temp.right == null) {
            Node current = temp.left == null ? temp.right : temp.left;
            if (getParent(temp.number, root).left == temp)
                getParent(temp.number, root).left = current;
            else
                getParent(temp.number, root).right = current;
        } else {
            Node successor = findMax(temp.left);
            int data = successor.number;
            deleteNode(temp.left, data);
            temp.number = data;
        }
    } else if (temp.number > n) {
        deleteNode(temp.left, n);
    } else {
        deleteNode(temp.right, n);
    }
}


回答5:

I know this is a very old question but anyways... The accepted answer's implementation is taken from c++, so the idea of pointers still exists which should be changed as there are no pointers in Java.

So every time when you change the node to null or something else, that instance of the node is changed but not the original one

This implementation is taken from one of the coursera course on algorithms.

public TreeNode deleteBSTNode(int value,TreeNode node)
{
    if(node==null)
    {
        System.out.println("the value " + value + " is not found");
        return null;
    }
    //delete
    if(node.data>value) node.left = deleteBSTNode(value,node.left);
    else if(node.data<value) node.right = deleteBSTNode(value,node.right);
    else{
        if(node.isLeaf())
            return null;
        if(node.right==null)
            return node.left;
        if(node.left==null)
            return node.right;

        TreeNode successor = findMax(node.left);
        int data = successor.data;
        deleteBSTNode(data, node.left);
        node.data = data;


    }
    return node;
}

All the links between the nodes are pertained using the return value from the recursion.