Deleting Value in Binary Tree - java

I have a slightly working binary search tree delete value function. The only time that it does not work is if you are trying to delete a root that has two children.
public boolean delete(BinaryTreeNode node, int i){
if (node == null){
return false;
} else {
if (node.getKey() == i){
BinaryTreeNode parent = new BinaryTreeNode(0, null, null);
parent.setLeftChild(root);
boolean result = deleteHelper(i, node, parent);
root = parent.getLeftChild();
return result;
} else {
return deleteHelper(i, node, null);
}
}
}
public boolean deleteHelper(int value, BinaryTreeNode curr, BinaryTreeNode parent){
if (value < curr.getKey()){
if (curr.getLeftChild() != null){
return deleteHelper(value, curr.getLeftChild(), curr);
} else {
return false;
}
} else if (value > curr.getKey()){
if (curr.getRightChild() != null){
return deleteHelper(value, curr.getRightChild(), curr);
} else {
return false;
}
} else {
if (curr.getRightChild() != null && curr.getLeftChild() != null){
curr.setKey(findMin(curr.getRightChild()).getKey());
deleteHelper(curr.getKey(), curr.getRightChild(), curr);
} else if (parent.getLeftChild() == curr){
parent.setLeftChild((curr.getLeftChild() != null)?curr.getLeftChild():curr.getRightChild());
} else if (parent.getRightChild() == curr){
parent.setRightChild((curr.getLeftChild() != null)?curr.getLeftChild():curr.getRightChild());
}
return true;
}
}

According to Wikipedia
Deleting a node with two children: Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node or its in-order predecessor node, R. Copy the value of R to N, then recursively call delete on R until reaching one of the first two cases.
http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
You can try by successor node as follows:
get successor of node to delete (current)
connect parent of current to successor
connect successor to the left child for current
For more details check out this link
Java, Binary tree remove method

Related

Deleting a node in a Binary Search Tree using Java

Could you tell me why this code wont delete a node in a BST? Is there any logical error in my code?
// To delete a node from the BST
public Node deleteNode(Node myRoot, int toDel) {
if (myRoot == null) return null;
else if (toDel < myRoot.data) myRoot.left = deleteNode(myRoot.left, toDel);
else if (toDel > myRoot.data) myRoot.right = deleteNode(myRoot.right, toDel);
else {
// Leaf node
if (myRoot.right == null && myRoot.left == null) {
myRoot = null;
} else if (myRoot.left == null) { // No left child
myRoot = myRoot.right;
} else if (myRoot.right==null){ // No right child
myRoot = myRoot.left;
}
}
return myRoot;
}
NOTE :- This code only deletes the nodes with one child or no child. I am currently working on deleting a node with 2 children so please dont solve that for me.
If 0 children, simply delete node (return null for it).
If there is 1 child, simply replace the node with the child that is not null.
public Node deleteNode(Node myRoot, int toDel) {
if (myRoot == null) {
return null;
} else if (myRoot.data == toDel) {
if (myRoot.left != null) {
return myRoot.left;
} else if (myRoot.right != null) {
return myRoot.right;
} else {
return null;
}
}
...
return myRoot;
}

Remove element from Binary Search Tree

I am doing an assignment, implementing own Binary Search Tree. The thing is, we have our own implementation of Node its parent is not directly accessible.
I have searched for answers, but I do not want to copy the solution entirely and I still don't seem to get it right, though. I miss some cases when the element is not removed.
Can you please help what am I doing wrong?
This is the remove method:
void remove(E elem) {
if(elem != null){
if (root != null && contains(elem)) {
removeFromSubtree(elem, root, null);
}
}
}
void removeFromSubtree(E elem, Node<E> current, Node<E> parent) {
if(elem.less(current.contents)){
if(current.left == null) return ;
removeFromSubtree(elem, current.left, current);
} else if(elem.greater(current.contents)){
if(current.right == null)return;
removeFromSubtree(elem, current.right, current);
} else {
if(current.left != null && current.right != null){
//both children
if(parent == null){
Node<E> n = new Node<>(null, null);
n.left = root;
removeFromSubtree(root.contents, n, null);
root = n.left;
root.setParent(null);
}
E min = subtreeMin(current.right);
current.contents = min;
removeFromSubtree(min, current.right, current);
} else if(current.left != null){
//left child
if (parent == null) {
root = current.left;
current.left.setParent(null);
return ;
}
setParentChild(current, parent, current.left);
} else if(current.right != null){
//right child
if (parent == null) {
root = current.right;
current.right.setParent(null);
return ;
}
setParentChild(current, parent, current.right);
} else {
if (parent == null) {
root = null;
return ;
}
setParentChild(current, parent, null);
}
}
}
Nodes use generic interface
class Node<E extends DSAComparable<E>>
which has just methods for comparation. It looks like this
interface DSAComparable<E extends DSAComparable<E>> {
boolean less(E other);
boolean greater(E other);
boolean equal(E other);
}
I use another methon inside remove that sets node's parent's child, depending if its left child or right child.
void setParentChild(Node<E> node, Node<E> parent,Node<E> value){
if(parent!= null){
if (parent.left == node) {
parent.left = value;
} else {
parent.right = value;
}
if(value!= null) value.setParent(parent);
}
}
Method subtreeMin(Node node) finds the smallest value in a subtree (the most left one)
Understanding your code is not so easy, since it still lacks of details.
I would refer to such an implementation of the Binary Search Tree that you can find online.
See for instance the one from Algorithms, 4th Ed..

Getting an object from a recursive deletion Java

I have a Binary Search Tree that contains nodes. Each node contains a key value and data value, and the nodes are sorted by key. I am trying to write a method to remove an object from my BST provided a key. Here is the code:
public Object remove(Comparable theKey) {
return remove(theKey, rootPtr).data;
}
public Node remove(Comparable theKey, Node node) {
Object o;
if(node == null)
return node;
if(theKey.compareTo(node.key) < 0) {
// go to left subtree
node.leftChild = remove(theKey, node.leftChild);
}else if(theKey.compareTo(node.key) > 0) {
//go to the right subtree
node.rightChild = remove(theKey, node.rightChild);
}else if(theKey.compareTo(node.key) == 0) {
if(node.leftChild != null && node.rightChild != null){
Node foundNode = findMin(node.rightChild);
node.key = foundNode.key;
node.data = foundNode.data;
node.rightChild = remove(node.key, node.rightChild);
}else{
if(node.leftChild != null){
node = node.leftChild;
}else{
node = node.rightChild;
}
}
}
numNodes--;
return node;
}
I would like to return the data value associated with the DELETED node. The issue I have is that: in the public Object remove() method, wouldn't the returned value always be the data value of the root node? I believe this would occur because the final returned call from the second method would be a reference to the rootPtr (root pointer). If this is the case, how can I save the data from the deleted node?
The simplest solution seems to be to add an output parameter than hands back the result:
public Object remove(Comparable theKey) {
Object[] result = new Object[1];
rootPtr = remove(theKey, rootPtr, result); // fix for deletion from a one-node tree
return result[0];
}
public Node remove(Comparable theKey, Node node, Object[] result) {
if(node == null) {
return node;
}
int diff = theKey.compareTo(node.key);
if (diff < 0) {
node.leftChild = remove(theKey, node.leftChild, result);
} else if (diff > 0) {
node.rightChild = remove(theKey, node.rightChild, result);
} else {
result[0] = node.key;
if (node.rightChild == null) {
node = node.leftChild;
} else if (node.leftChild == null) {
node = node.rightChild;
} else {
Node foundNode = findMin(node.rightChild);
node.key = foundNode.key;
node.data = foundNode.data;
node.rightChild = remove(node.key, node.rightChild, new Object[1]);
}
numNodes--;
}
return node;
}
Returning the found node doesn't work without significant changes because the return parameter is used to replace nodes as needed, and in the case where the found node has two children, you'd need to make a copy or insert a new node. Handling the case where the root node gets removed would be an issue, too.
p.s. I am assuming this is not a "trick question" and you can't just return theKey -- which has to equal the found key after all :)
You have to return the value, that you are receiving from the recursive remove-call.
p.ex:
if(theKey.compareTo(node.key) < 0) {
// go to left subtree
return remove(theKey, node.leftChild);
}else if ...
Now you will run throught the tree, until you find the correct node and that node will be given to the node which is the parent of the node to remove, and the parent will than give it to his parent and so on, until the root will return the node to his caller.

java Delete a Binary Tree node containing two children

This is the last case where the node to be deleted has two children. I cant figure out what I am doing wrong . Please help.
//BTNode has two children
else if (u.getLeft() != null && u.getRight() != null){
//if node to delete is root
BTNode<MyEntry<K,V>> pred = u.getRight();
while (pred.getLeft().element() != null){
pred = pred.getLeft();
}
BTNode<MyEntry<K,V>> predParent = pred.getParent();
if (!hasRightChild(pred)){
predParent.setLeft(new BTNode<MyEntry<K,V>>(null,predParent,null,null));}
if (hasRightChild(pred)){
BTNode<MyEntry<K,V>> predChild = pred.getRight();
predParent.setLeft(predChild);
predChild.setParent(predParent);
}
return returnValue;
ok so modify it like this ??
u.setElement(succ.element());
BTNode<MyEntry<K,V>> succParent = succ.getParent();
if (!hasLeftChild(succ)){
succParent.setRight(new BTNode<MyEntry<K,V>>(null,succParent,null,null));}
if (hasLeftChild(succ)){
BTNode<MyEntry<K,V>> predChild = succ.getLeft();
succParent.setRight(predChild);
predChild.setParent(succParent);
}
return returnValue;
From wikipedia:
Deleting a node with two children: Call the node to be deleted N. Do
not delete N. Instead, choose either its in-order successor node or
its in-order predecessor node, R. Replace the value of N with the
value of R, then delete R.
So, take for example the left children, and then find the rightmost leaf in that subtree, then replace the information of the node to delete with that of the leaf, and then delete that leaf easily.
You might want to create a function that returns the rightmost leaf from a subtree.
I have given the code for deletion of a node in a BST which would work for any condition and that too using a for loop.
public void delete(int key) {
Node<E> temp = find(key);
System.out.println(temp.key);
for (;;) {
// case 1 : external node
if (temp.isExternal()) {
if (temp.getParent().getrChild() == temp) {
temp.parent.rightchild = null;
temp = null;
} else {
temp = null;
}
break;
}
// case2 : one child is null
else if ((temp.getlChild() == null) || (temp.getrChild() == null)) {
if ((temp.parent.leftchild != null) && temp.getParent().getlChild().key == temp.key) {
if (temp.getlChild() == null) {
temp.getParent().setLeft(temp.getrChild());
temp.getrChild().setParent(temp.getParent());
break;
}
else
temp.getParent().setLeft(temp.getlChild());
temp.getlChild().setParent(temp.getParent());
}
else {
if (temp.rightchild != null) {
System.out.println("in");
temp.getParent().setRight(temp.getrChild());
temp.getrChild().setParent(temp.getParent());
break;
}
else
temp.getParent().setRight(temp.getlChild());
temp.getlChild().setParent(temp.getParent());
}
break;
}
// case 3 : has both the children
else {
int t = temp.key;
temp.key = temp.getlChild().key;
temp.getlChild().key = t;
temp = temp.getlChild();
continue;
}
}
}

Finding min element of binary search tree

I am having trouble finding the smallest element of a binary search tree. I have some code finished, but it is not working.
public T getMinElement(TreeNode<T> node) {
//TODO: implement this
if (node == null){
return null;
}
if (node.getLeftChild() == null){
return (T) node;
}
else{
return getMinElement(node);
}
}
You were almost there! You just need to recurse on the left child of your binary search tree (always guaranteed to be smaller). Also you had some syntax errors, which I fixed.
public <T> T getMinElement(TreeNode<T> node) {
if (node == null){
return null;
}
if (node.getLeftChild() == null){
return node.getData(); // or whatever your method is
} else{
return getMinElement(node.getLeftChild());
}
}

Categories