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;
}
Related
So I have a binary tree with data and I have currently written a remove method for the binary tree that should remove a node while still maintaining the binary tree as a balanced tree.
Currently I am doing the remove like this:
public Node remove(K key) {
return removeHelper(key, root, null);
}
public Node removeHelper(K key, Node targetNode, Node parent) {
if (targetNode == null) {
return targetNode;
} else {
if (key.compareTo(targetNode.key) == 0) {
// we have found the item we are looking for!
// CASE #1 - The target node does not have any children
if (targetNode.left == null && targetNode.right == null) {
if (parent != null) {
if (parent.left.equals(targetNode)) {
parent.left = null;
} else if (parent.right.equals(targetNode)) {
parent.right = null;
}
}
// CASE #2. target node only has a one child, right or left.
} else if (targetNode.left == null) {
targetNode = targetNode.right;
} else if (targetNode.right == null) {
targetNode = targetNode.left;
// CASE #3 - It has 2 children.
} else {
Node temp = targetNode;
Node rightMin = FindMin(temp.right);
targetNode.key = rightMin.key;
targetNode.value = rightMin.value;
}
} else if (key.compareTo(targetNode.key) < 0) {
return removeHelper(key, targetNode.left, targetNode);
} else if (key.compareTo(targetNode.key) > 0) {
return removeHelper(key, targetNode.right, targetNode);
} else {
return targetNode;
}
}
return targetNode;
}
and here is the FindMin method:
//Finding the minimum node in this subtree passed in
private Node FindMin(Node rootNode) {
if (rootNode.left == null) {
return rootNode;
} else {
return FindMin(rootNode.left);
}
}
And then I am trying to test the removal of nodes like such:
BinarySearchTree<Integer, String> tree = new BinarySearchTree<Integer, String>();
tree.put(40, "Forty");
tree.put(20, "Twenty");
tree.put(60, "Sixty");
tree.put(10, "Ten");
tree.put(30, "Thirty");
tree.put(50, "Fifty");
tree.put(70, "Seventy");
tree.put(4, "four");
tree.remove(70);
tree.remove(60);
System.out.println(tree);
And the output from this is:
(4:four)(10:Ten)(20:Twenty)(30:Thirty)(40:Forty)(50:Fifty)(60:Sixty)
As you can see, the 70 is being remove successfully but the 60 is not being removed for some reason. I tried changing around my code a bit but I usually run into a stackoverflow error when doing so.
Anyone see an issue or case I am missing here?
I implemented recursive algorihtm for deleting nodes in BST, but it seems not to work properly in case in which the node to be deleted has two children. Here is a code for method used to delete nodes:
public boolean delete(int val)
{
Node nodeToBeDeleted = find(val);
if(nodeToBeDeleted != null)
{
//case 1: node has no children
if(nodeToBeDeleted.leftChild == null && nodeToBeDeleted.rightChild == null)
deleteCase1(nodeToBeDeleted);
//case 3: node has two children
else if(nodeToBeDeleted.leftChild != null && nodeToBeDeleted.rightChild != null)
{
deleteCase3(nodeToBeDeleted);
}
//case 2: node has one child
else if(nodeToBeDeleted.leftChild != null)
{
//case 2 where left child should be deleted
deleteCase2(nodeToBeDeleted);
}
else if(nodeToBeDeleted.rightChild != null)
{
//case 2 where right child should be deleted
deleteCase2(nodeToBeDeleted);
}
return true;
}
else
return false;
}
And here deleteCase1, deleteCase2 and deleteCase3 methods:
private void deleteCase1(Node nodeToBeDeleted)
{
//check if node to be deleted is a left or a right child of the parent of the node to be deleted
if(nodeToBeDeleted.parent.leftChild == nodeToBeDeleted)
{
nodeToBeDeleted.parent.leftChild = null;
}
else if(nodeToBeDeleted.parent.rightChild == nodeToBeDeleted)
{
nodeToBeDeleted.parent.rightChild = null;
}
}
Here find method:
public Node find(int val)
{
if(root != null)
{
return findNode(root, new Node(val));
}
return null;
}
private Node findNode(Node search, Node node)
{
if(search == null)
return null;
if(search.data == node.data)
{
return search;
}
else
{
Node returnNode = findNode(search.leftChild, node);
if(returnNode == null)
{
returnNode = findNode(search.rightChild, node);
}
return returnNode;
}
}
minLeftTreversal method:
private Node minLeftTreversal(Node node)
{
if(node.leftChild == null)
return node;
return minLeftTreversal(node.leftChild);
}
Structure of the tree looks like this:
enter image description here
Algorithm works if I delete 75, but if I try to delete 25 it messes up.
Thank you in advance!
Your first if statement in public boolean delete(int val) is missing the { and }
//case 1: node has no children
if(nodeToBeDeleted.leftChild == null && nodeToBeDeleted.rightChild == null)
{ // <---- ADD THIS
deleteCase1(nodeToBeDeleted);
} // <---- AND ADD THIS
//case 3: node has two children
else if(nodeToBeDeleted.leftChild != null && nodeToBeDeleted.rightChild != null)
{
deleteCase3(nodeToBeDeleted);
}
Hi I'm having trouble getting this code working correctly. It seems to be jumping out of the stack when it recurses all the way down the leftmost edge of the tree. I just can't seem to figure this one out.
public static Node lookup(Node node, int lookupValue) {
if (node == null) {
return null;
} else {
if (node.value == lookupValue) {
System.out.println("Found");
return node;
} else if(node.left != null) {
return lookup(node.left, lookupValue);
} else if(node.right != null) {
return lookup(node.right, lookupValue);
} else {
return null;
}
}
}
You return whatever is returned form the left sub-tree (if present) without checking the right one. A lot of the else branching isn't necessary when there is a return statement in the if block. Change as follows:
public static Node lookup(Node node, int lookupValue) {
if (node == null)
return null;
if (node.value == lookupValue)
// System.out.println("Found");
return node;
Node rval = lookup(node.left, lookupValue);
// only return if found in left sub-tree
return (rval != null) ? rval : lookup(node.right, lookupValue);
}
Your else if are not correct you chould check the left and right everytimes:
if (node == null) return null;
if (node.value == lookupValue) {
System.out.println("Found");
return node;
}
Node found = lookup(node.left, lookupValue);
if(found != null) {
return found;
}
return lookup(node.right, lookupValue);
I am trying to implement leafCount() and nodeCount() to this recursive binary tree - program.
When testing it, these two methods (or the tests of them) throw AssertionError, so obviously they're not working as expected. I cannot figure out where I'm doing or thinking wrong. If someone could explain what I'm doing wrong or pinpoint the problem, I would be very grateful.
public class BSTrec {
BSTNode tree, parent, curr;
public BSTrec () {
tree = null; // the root of the tree
parent = null; // keeps track of the parent of the current node
curr = null; // help pointer to find a node or its place in the tree
}
public boolean isEmpty() {
return tree == null;
}
private boolean findNodeRec(String searchKey, BSTNode subtree, BSTNode subparent) {
if (subtree == null) { // base case 1: node not found
curr = null;
parent = subparent; // the logical parent for the value
return false;
}
else {
if (subtree.info.key.equals(searchKey)) {
curr = subtree; // update current to point to the node
parent = subparent; // update parent to point to its parent
return true;
}
else {
if (searchKey.compareTo(subtree.info.key) < 0) {
return findNodeRec(searchKey, subtree.left, subtree);
}
else {
return findNodeRec(searchKey, subtree.right, subtree);
}
}
}
}
public NodeInfo retrieveNode(String searchKey) {
if (findNodeRec(searchKey, tree, null)) return curr.info;
else return null;
}
public void addRec(String keyIn, BSTNode subtree, BSTNode subparent, boolean goLeft) {
if (tree == null) { // a first node will be the new root: base case 1
tree = new BSTNode(new NodeInfo(keyIn));
curr = tree;
parent = null;
}
else { // insertion in an existing tree
if (subtree == null) {
if (goLeft) {
subparent.left = new BSTNode(new NodeInfo(keyIn));
curr = subparent.left;
parent = subparent;
}
else { // the new node is to be a left child
subparent.right = new BSTNode(new NodeInfo(keyIn));
curr = subparent.right;
parent = subparent;
}
}
else {
if (keyIn.compareTo(subtree.info.key) < 0) {
addRec(keyIn, subtree.left, subtree, true);
}
else {
addRec(keyIn, subtree.right, subtree, false);
}
}
}
}
public void deleteNode(String searchKey) {
boolean found = findNodeRec(searchKey, tree, null);
if (!found) // the key is not in the tree
System.out.println("The key is not in the tree!");
else {
if ((curr.left == null) && (curr.right == null))
if (parent == null)
tree = null;
else
if (curr == parent.left) // delete a left child
parent.left = null;
else // delete a right child
parent.right = null;
else // delete a node with children, one or two
if ((curr.left != null) && (curr.right != null)) { // two children
BSTNode surrogateParent = curr;
BSTNode replacement = curr.left;
while (replacement.right != null) {
surrogateParent = replacement;
replacement = replacement.right;
}
curr.info = replacement.info; // the information is copied over
if (curr == surrogateParent) {
curr.left = replacement.left; // curr "adopts" the left
replacement = null;
}
else {
surrogateParent.right = replacement.left;
replacement = null;
}
} // End: if two children
else { // delete a node with one child
if (parent == null)
if (curr.left != null)
tree = curr.left;
else
tree = curr.right;
else
if (curr == parent.left)
if (curr.right == null)
parent.left = curr.left;
else
parent.left = curr.right;
else
if (curr.right == null)
parent.right = curr.left;
else
parent.right = curr.right;
}
curr = null;
}
}
public void inOrder(BSTNode root) {
if (root != null) {
inOrder(root.left); // process the left subtree
System.out.println(root.info.key); // process the node itself
inOrder(root.right); // process the right subtree
}
}
public void preOrder(BSTNode root) {
if (root != null) { // implicit base case: empty tree: do nothing
System.out.println(root.info.key); // process the node itself
preOrder(root.left); // process the left subtree
preOrder(root.right); // process the right subtree
}
}
public void postOrder(BSTNode root) {
if (root != null) { // implicit base case: empty tree: do nothing
postOrder(root.left); // process the left subtree
postOrder(root.right); // process the right subtree
System.out.println(root.info.key); // process the node itself
}
}
public int nodeCount() {
int count = 0;
if (tree == null) {
count = 0;
//throw new NullPointerException();
}
else {
if (tree.left != null) {
count = 1;
count += tree.left.nodeCount();
}
if (tree.right != null) {
count = 1;
count += tree.right.nodeCount();
}
}
return count;
}
public int leafCount() {
int count = 0;
if (tree == null) {
return 0;
}
if (tree != null && tree.left == null && tree.right==null) {
return 1;
}
else {
count += tree.left.leafCount();
count += tree.right.leafCount();
}
return count;
}
private class BSTNode {
NodeInfo info;
BSTNode left, right;
BSTNode() {
info = null;
left = null;
right = null;
}
public int leafCount() {
// TODO Auto-generated method stub
return 0;
}
public int nodeCount() {
// TODO Auto-generated method stub
return 0;
}
BSTNode(NodeInfo dataIn) {
info = dataIn;
left = null;
right = null;
}
BSTNode(NodeInfo dataIn, BSTNode l, BSTNode r) {
info = dataIn;
left = l;
right = r;
}
}
}
public class NodeInfo {
String key; // add other fields as needed!
NodeInfo() {
key = null;
}
NodeInfo(String keyIn) {
key = keyIn;
}
}
Your nodeCount logic has an error :
if (tree.left != null) {
count = 1;
count += tree.left.nodeCount();
}
if (tree.right != null) {
count = 1; // here you initialize the count, losing the count of the left sub-tree
count += tree.right.nodeCount();
}
Change to
if (tree.left != null || tree.right != null) {
count = 1;
if (tree.left != null) {
count += tree.left.nodeCount();
}
if (tree.right != null) {
count += tree.right.nodeCount();
}
}
In your leafCount you are missing some null checks, since it's possible one of the children is null :
if (tree != null && tree.left == null && tree.right==null) {
return 1;
} else {
if (tree.left != null) // added check
count += tree.left.leafCount();
if (tree.right != null) // added check
count += tree.right.leafCount();
}
In here:
public int leafCount() {
int count = 0;
if (tree == null) {
return 0;
}
if (tree != null && tree.left == null && tree.right==null) {
return 1;
}
else {
count += tree.left.leafCount();
count += tree.right.leafCount();
}
return count;
}
you're not allowing for the possibility that tree.left is non-null but tree.right is null. In that case, you'll try to execute
count += tree.right.leafCount();
which will throw a NullPointerException.
I think you should also rethink what you're doing with your instance fields curr and parent. These really should be local variables in whatever method you need to use them in. A tree doesn't have a "current" node in any meaningful sense.
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;
}
}
}