I have the classes BinaryTreeNode(int value) with its left and right child and BinaryTree(int rootVal) with BinaryTreeNode root with rootVal as its value. I developed a code to calculate the number of nodes in the tree (in class BinaryTreeNode), but it doesn't work because of a NullPointerException:
public int size(){
if(this == null) { // base case
return 0;
} else {
return 1 + left.size() + right.size();
}
}
However another solution I found, with a similar strategy, works:
public int size(BinaryTreeNode refNode){
if(refNode == null) { // base case
return 0;
} else {
return 1 + size(refNode.left) + size(refNode.right);
}
}
I have understood why my code throws an exception (it is because left/right would point to null). But I would like to understand why the second solution works with quasi the same principle. Thank you in advance!
Size() function recursively calculates the size of a tree. It works as follows: Size of a tree = Size of left subtree + 1 + Size of right subtree.
The height of a binary tree is found using the recursive Depth-First Search (DFS) algorithm, as shown below: Base case: If there is no node, return 0. Else: If there are 1 or 2 children, return the maximum of the height of the left and right sub-trees, plus 1 to account for the current node.
In your first example you try to find the size before you check for null
:
first you call
left.size()
and then inside the size()
method you check to see if the object you just called the method on is null
if(this == null) { // base case
return 0;
...
so if left
is null
, you get the NPE before you get into the size()
method.
The main thing to remember here, is that this
can never be null
. If it was, you couldn't be running a method on it in the first place. So you weren't actually terminating your recursion on a null
case like you thought you were.
In the second you check for null
first:
if refNode.left is null
here
return 1 + size(refNode.left) + size(refNode.right);
the size()
method does a pre-check
if(refNode == null) { // base case
return 0;
...
and safely returns 0
.
You could make your first method work by explicitly putting the null-check first on each branch:
public int size(){
return 1
+ left == null ? 0 : left.size() // check for null first
+ right == null ? 0 : right.size(); // check for null first
}
The base case is organized in the wrong way; checking for null
on the current instance makes no sense. The method should be rewritten as follows.
public int size(){
int sizeLeft = 0;
if (this.left != null)
sizeLeft = left.size();
int sizeRight = 0;
if (this.right != null)
sizeRight = right.size();
return 1 + sizeLeft + sizeRight;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With