I'm confused on why my removal method of leaves in a BST is not working. If I assign 0 to the data, its reflected in the tree, but when I assign null to the node, it's still able to be referenced in the BST traversal.
public void removeLeaves(){
removeLeaves(getRoot());
}
private void removeLeaves(IntTreeNode node) {
if (node == null)
return;
else if( node.left == null && node.right == null){
node.data = 0; //im finding the leave nodes correctly
node = null; //but its not removing them
}
else {
removeLeaves(node.left);
removeLeaves(node.right);
}
}
overallRoot
____[7]____
/ \
[3] [9]
/ \ / \
[0] [0] [0] [8]
\
[0]
Could somebody explain why this is not working as intended?
In your example tree , consider 9
9.left => null
9.right => address of 8
when you assign node.data = 0; , node has address of 8 so 0 will be reflected in the tree.
But when you do node =null, you are just changing the variable node. you are not doing any operation on address of 8.
I think what you are hoping to happen is by doing node = null is:
address of 8 = null
which is actually not possible, because you are just changing the variable node.
Say address of 8 is 0XABCD, so node = 0XABCD.
when you do node.data=0 as node has address 0XABCD, 0XABCD.data will be changed to 0. but when you do node = null, you are just assigning a new value to a variable node, you are not doing any operation on the original address 0XABCD.
What you actually have to do is
if(node.left!= null && node.left.left == null && node.left.right ==null)
node.left =null
if(node.right!= null && node.right.left == null && node.right.right ==null)
node.right =null
UPDATE
What you are trying to do is something like this:
Foo foo = new Foo();
Foo anotherFoo = foo;
anotherFoo.value = something; // both foo.value and anotherFoo.value will be changed to "something", because of the reference.
anotherFoo = null;
// here you are expecting foo also to be null which is not correct.
public void removeLeaves () {
if (getRoot() != null)
removeLeaves (getRoot());
}
private IntTreeNode removeLeaves (IntTreeNode node) {
if (getRoot().left == null && getRoot().right == null) {
setRoot(null);
} else {
if (node.left != null) {
if (node.left.left == null && node.left.right == null)
node.left = null;
else
removeLeaves(node.left);
}
if (node.right != null) {
if (node.right.right == null && node.right.left == null)
node.right = null;
else
removeLeaves(node.right);
}
}
return node;
}
Related
I am trying to write binary search insert method but it gives the wrong answer. I couldn't find what is the reason. Here's my code:
public static Node insert(Node root,int data) {
Node insertedNode = new Node(data);
if(root == null){
root=insertedNode;
}
else {
Node node = root;
Node insertedNode = new Node(data);
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
if (data > root.data) {
root.left = insertedNode;
}
else {
root.right=insertedNode;
}
}
}
The problem is very easy to detect. Look at your while:
while(root.left !=null && root.right !=null){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
It will only seek to deeper levels if both left and right of root exists. So, let's suppose you try to add 2, 3, 4. You insert 2, which will become your root. Then, you try to add 3. Your while detects that it's not true that both of left and right of root are not null. So, it will add 3 to the right. So far, so good:
2
\
3
Now, you try to add 4. Your while checks whether root.left and root.right are not null. It's false, so it will be the right of the root, resulting in
2
\
4
instead of
2
\
3
\
4
Let's fix your while:
while((root != null) && (((root.data < data) && (root.left != null)) || ((root.data > data) && (root.right != null)))){
if(root.left.data>data){
root=root.left;
}
else {
root=root.right;
}
}
I'm writing a method for a homework problem on binary trees.
Objective:
Given a binary tree, check if the tree satisfies the property that for each node, the sum of the values of its left and right children are equal to the node's value. If a node has only one child, then the node should have the same value as that child. Leaf nodes automatically satisfy the property.
I am getting an error that my code is not correct for all cases. For example if I have a tree
15
/ \
5 10
I am returning false when it should be true.
Here is my method so far, what am I doing wrong?
boolean BTchecksum(BinNode root) {
if (root == null || root.left() == null && root.right() == null) {return true;}
BinNode leftNode = root.left();
BinNode rightNode = root.right();
int sum = (int)(leftNode.element()) + (int)(leftNode.element());
int value = (int)(root.element());
return (sum == value) && BTchecksum(root.left()) && BTchecksum(root.right());
}
You wrote sum as:
leftNode.element()) + (int)(leftNode.element)));
Should be this:
leftNode.element()) + (int)(rightNode.element)));
Right now, you're probably getting null pointer exceptions because you're referencing children that may be null. This may not be the most efficient solution, but it takes care of all the cases.
public boolean BTchecksum(BinNode root) {
if (root == null || root.right()==null && root.left()==null) {
return true;
}
if (root.right() == null) {
return (root.left().value() == root.value())
&& BTchecksum(root.left());
} else if (root.left() == null) {
return (root.right().value() == root.value())
&& BTchecksum(root.right());
} else {
return (root.value() == root.left().value() + root.right().value())
&& BTchecksum(root.left()) && BTchecksum(root.right());
}
Revision (no NullPinterException)
public boolean BTchecksum(BinNode root)
{
if (root == null || root.left() == null && root.right() == null) {return true;}
int sum = 0;
if (root.left() != null){sum = sum + root.left().value();}
if (root.right() != null){sum = sum + root.right().value();}
return (sum == root.value()) && BTchecksum(root.left()) && BTchecksum(root.right());
}
I am finding the 'next' node (i.e., in-order successor) of a given node in a binary search tree.
Why is this condition used in the code given below:
if (n.parent == null || n.right != null)
My question is: Why are we checking for n.parent == null ?
Full Code:
public static TreeNode inorderSucc(TreeNode n) {
if (n == null) return null;
// Found right children -> return left most node of right subtree
if (n.parent == null || n.right != null) {
return leftMostChild(n.right);
} else {
TreeNode q = n;
TreeNode x = q.parent;
// Go up until we’re on left instead of right
while (x != null && x.left != q) {
q = x;
x = x.parent;
}
return x;
}
}
public static TreeNode leftMostChild(TreeNode n) {
if (n == null) {
return null;
}
while (n.left != null) {
n = n.left;
}
return n;
}
if (n.parent == null || n.right != null)
Checking if n is the root node and it has a right subtree.
I have been working on creating a Binary Tree from scratch, not using built-in libraries. I am working on a function called "pruneLeaves". The job is to remove all leaves of the tree; nodes with no children.
When I step through the function with breakpoints, it appears to be removing the leaves and even prints out that it is indeed removing the proper nodes. However, when I display the tree in my main function afterwards, the nodes are still there!
I have tried for hours to figure this out, what am I overlooking?!
Program Output:
Num nodes = 9
Pruning.
12
Leaf removed
9
Leaf removed
4
Leaf removed
Tree after pruning..
3 4 5 6 7 8 9 11 12
// Recursive helper. Accepts BinaryNode as a parameter
private BinaryNode pruneLeaves(BinaryNode t) {
// If we have no left child AND no right child, we are a leaf
if ((t.left == null) && (t.right == null)) {
//Print the element being removed.
System.out.println (t.element);
//Remove the element
t = remove(t.element, t);
if(t == null)
System.out.println("Leaf removed");
}
// Else we have at least one child
else {
if (t.right != null) {
pruneLeaves(t.right);
}
if (t.left != null) {
pruneLeaves(t.left);
}
}
//Return our leafless tree
return t;
}
// Main recursive method, call the helper method by passing the root of the
// tree, which calls it.
public void pruneLeaves () {
pruneLeaves(this.getRoot());
}
BinaryNode getRoot () {
return this.root;
}
/**
* Internal method to remove from a subtree.
* #param x the item to remove.
* #param t the node that roots the tree.
* #return the new root.
*/
private BinaryNode remove( int x, BinaryNode t ) {
success = false;
if( t == null )
return t; // Item not found; do nothing
if( x < t.element )
t.left = remove( x, t.left );
else if( x > t.element )
t.right = remove( x, t.right );
else {
success = true;
if( t.left != null && t.right != null ) { // Two children
t.element = findMin( t.right ).element;
t.right = remove( t.element, t.right );
}
else
t = ( t.left != null ) ? t.left : t.right;
}
return t;
}
And my main method, calling the function:
public static void main( String [ ] args ) {
BST t = new BST( );
t.insert(7);
t.insert(6);
t.insert(5);
t.insert(3);
t.insert(4);
t.insert(8);
t.insert(11);
t.insert(9);
t.insert(12);
System.out.println();
System.out.println ("Num nodes = " + t.countNodes());
System.out.println ("Pruning.");
// Remove leaves of the tree
t.pruneLeaves();
t.infix();
System.out.println();
}
Using the link: Deleting Leaves From a Binary Tree
I have found the errors in my code and corrected them using the answer given in the link.
Correct Code as follows:
private BinaryNode pruneLeaves (BinaryNode p) {
// There is a left child
if (p.left != null)
if (isLeaf(p.left)) //Is that child a leaf?
p.left = null;
else
pruneLeaves(p.left); // If it is not, recursive call
// Is there a right child
if (p.right != null)
if (isLeaf(p.right))
p.right = null;
else
pruneLeaves(p.right); // Recursive call
return p;
}
// Main recursive call, passes the root of calling tree to the helper method
public void pruneLeaves () {
pruneLeaves (this.getRoot());
}
// Returns true if child is a leaf
boolean isLeaf (BinaryNode t) {
if (t.left == null && t.right == null) {
return true;
}
return false;
}
+1 for being right answer (only one I've found so far), but you forgot the null scenario for the root, and also to remove the root if the root itself has no children. Here's how I did it - I used your code and then made sure it fit all scenarios:
public void removeLeaves () {
if (root != null) {
removeLeaves (root);
} else {
return;
}
}
private Node removeLeaves (Node node) {
if (root.left == null && root.right == null) {
root = null;
} else {
if (node.left != null) {
if (node.left.left == null && node.left.right == null) {
node.left = null;
} else {
removeLeaves(node.left);
}
}
if (node.right != null) {
if (node.right.left == null && node.right.right == null) {
node.right = null;
} else {
removeLeaves(node.right);
}
}
}
return node;
}
This code ensures that all nodes with no children are removed, and also eliminates the need for the isLeaf() function.
I'm trying to write a method, which returns the parent node of a given node.
public BinarySearchTreeNode<T> getParent(BinarySearchTreeNode<T> e) {
if (e == null) {
return null;
}
BinarySearchTreeNode<T> current = this.root;
T eValue = e.getValue();
while (current != null) {
if (howManyChildren(current) == 0) {
return null;
} else if (eValue.equals(current.getLeft().getValue())
|| eValue.equals(current.getRight().getValue())) {
return current;
} else if (eValue.compareTo(current.getValue()) < 0) {
current = current.getLeft();
} else {
current = current.getRight();
}
}
return null;
}
However I receive NullPointerExceptions, when one or both of the children are null-nodes and equals tries to compare the value with null.
How do I go on to fix this? I'm still new to Java.
You really need to check that the children are not null before you call a method on them. In this case you call current.getLeft().getValue() but the left child might be null. If it's null you will get the NullPointerException.
The following is an example with checking to make sure they aren't null before calling the method. Caveat, I didn't check to see if the entire code was correct besides the NullPointerException.
public BinarySearchTreeNode<T> getParent(BinarySearchTreeNode<T> e) {
if (e == null) {
return null;
}
BinarySearchTreeNode<T> current = this.root;
T eValue = e.getValue();
while (current != null) {
if (howManyChildren(current) == 0) {
return null;
} else if ((current.getLeft()!=null && eValue.equals(current.getLeft().getValue()))
|| (current.getRight()!=null) && eValue.equals(current.getRight().getValue())) {
return current;
} else if (eValue.compareTo(current.getValue()) < 0) {
current = current.getLeft();
} else {
current = current.getRight();
}
}
return null;
}
With object variables, when the value is null there is no object there that can supply the methods you would be calling.
You compare an object variable's value to null with:
if (obj == null) {
... do whatever ...
}
You can compare an object to null in many cases like this:
if (obj.equals(null)) ...
or
String s = null;
if (obj.equals(s)) ... this works
if (s.equals(obj)) ... this doesn't work
Note
In your code, if the node you are searching for is the root, it will never find it.
Similarly, you check all the children to see if they match and then you decide which of the children could match by comparing the value to the parent. Maybe you should reorder things a bit so you test the current node
If it's null, the search has ended in failure
If it matches, return its parent which you saved on the last iteration.
If it doesn't match, get the correct child -- right or left -- based on the value and loop.
This has the advantage that you only get the value of nodes when you know they aren't null.
T eValue = e.getValue();
BinarySearchTreeNode<T> prev = null;
BinarySearchTreeNode<T> current = this.root;
while (current != null) {
int compare = eValue.compareTo(current.getValue());
if (compare == 0) {
return prev;
}
prev = current; // save the parent in case it matches
if (compare < 0) {
current = current.getLeft();
} else {
current = current.getRight();
}
}