Binary search tree null pointer exception with traversal [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I am implementing a binary search tree in java, writing the methods recursively. I did the insert methods, and now I am stuck on the first traversal method, the in order one. When I call it in my test code, after adding a few elements, (tree.inorderTraversal), I get a null pointer exception at the rescursive in order method, and I don't see why. Could it be something wrong with the insert method?
public void insertInBinaryTree(E newItem)
{
BinaryTreeNode<E> node = new BinaryTreeNode<E>(newItem);
if (root == null) {
root = node;
} else {
insert(root, newItem);
}
}
// Recursively insert a node containing newItem into a non-empty tree. Used
// by insertInBinaryTree
private void insert(BinaryTreeNode<E> treeNode, E newItem)
{
if (newItem.compareTo(treeNode.getItem()) < 0) {
if (treeNode.getLeftChild() != null) {
insert(treeNode.getLeftChild(), newItem);
}
else {
treeNode.setLeftChild(new BinaryTreeNode<E>(newItem));
}
}
else {
if (treeNode.getRightChild() != null) {
insert(treeNode.getRightChild(), newItem);
}
else {
treeNode.setRightChild(new BinaryTreeNode<E>(newItem));
}
}
}
// If the tree is not empty, initiates an inorder traversal. This should
// print all items in ascending order. If the tree is empty, just prints
// "Tree is empty"
public void inorderTraversal()
{
System.out.println("\nInorder Traversal");
if (root == null) {
System.out.println("Tree is empty");
} else {
inorder(root);
}
}
// Recursive inorder traversal of a non-empty tree. Used by
// inorderTraversal.
private void inorder(BinaryTreeNode<E> treeNode)
{
inorder(treeNode.getLeftChild());
System.out.print(treeNode.getItem());
inorder(treeNode.getRightChild());
}

In the inorder method, since its recursive method the first statement should check for null on the argument and if it is so it should return. Otherwise the recursion never ends and it runs into NPE when accessing treeNode.getLeftChild() or treeNode.getRightChild() on possible null when there is no left child node or right child node.

You are missing NULL check. It should be
private void inorder(BinaryTreeNode<E> treeNode)
{
if(treeNode != null)
{
inorder(treeNode.getLeftChild());
System.out.print(treeNode.getItem());
inorder(treeNode.getRightChild());
}
}

Related

I want to add a generic element to this linked list in an ordered way

public void add(T element)
{
LinearNode<T>previous=head;
LinearNode<T>current=head.getNext();
LinearNode<T>node= new LinearNode<>();
if(!(element instanceof Comparable))
{
throw new NonComparableElementException("OrderList");
}
Comparable<T>comparableElement= (Comparable<T>)element;
if(comparableElement.compareTo(head.getElement())<0)
{
head=node;
}
else
{
while(current!=null && comparableElement.compareTo(current.getElement())>0)
{
previous=current;
current=current.getNext();
}
previous.setNext(node);
}
count++;
}
I have been trying to write this add method which adds the specified element to this list at the location determined by the element's natural ordering but it gives an error:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "jsjf.LinearNode.getNext()" because "this.head" is null
at jsjf.LinkedOrderedList.add(LinkedOrderedList.java:36)
at jsjf.LinkedListTester.main(LinkedListTester.java:8)
As for the error:
Exception in thread "main" java.lang.NullPointerException: Cannot
invoke "jsjf.LinearNode.getNext()" because "this.head" is null at
jsjf.LinkedOrderedList.add(LinkedOrderedList.java:36) at
jsjf.LinkedListTester.main(LinkedListTester.java:8)
The error is due to line 4:
LinearNode<T>current=head.getNext();
You should do a null check before accessing the head's contents. If the head is null, then simply insert at head:
if (head == null) {
head = comparableElement;
return;
}
Explanation:
There are four cases you need to consider when adding an element to an ordered LinkedList:
When insertion happens at the beggining (you covered this case).
When insertion happens to an empty LinkedList.
When insertion happens at the end of the list (you covered this case).
When insertion happens in the middle of the list.
I've edited your code and made the necessary additions for it to work:
public void add(T element) {
// Create new node and store data in it
LinearNode<T> comparableElement = new LinearNode<>(element);
LinearNode<T> prev = null, curr = head;
if (!(element instanceof Comparable)) {
throw new NonComparableElementException("OrderList");
}
// Decide where to add new node in LinkedList
while (curr != null && curr.getData().compareTo(comparableElement.getData()) < 0) {
prev = curr;
curr = curr.getNext();
}
// Add node in LinkedList
if (head == null) { // Case 0: Empty LinkedList
head = comparableElement;
} else if (prev == null) { // Case 1: Insert at beginning
comparableElement.setNext(head);
head = comparableElement;
} else if (curr != null) { // Case 2: Insert in between
prev.setNext(comparableElement);
comparableElement.setNext(curr);
} else // Case 3: Insert at the end
prev.setNext(comparableElement);
count++;
}
What the code essentially does is it loops to the correct insertion position and manipulates the pointers accordingly to insert the item.

Method going to second returning, resulting in false output

I'm trying to find a specific node in a binary tree using Java. My method for finding the node returns the node that contains the data that was searched for.
My code looks like this:
public BinNode find(Comparable item) throws NullPointerException {
if (item == null) {
throw new NullPointerException("item is NULL");
} else if (root == null) {
throw new NullPointerException("tree is empty");
}
return find(root, item);
}
public static boolean found = false;
public BinNode find(BinNode k, Comparable item) throws NullPointerException {
if (k.getData().equals(item)) {
found = true;
return k;
}
if (!found && k.getChildLeft() != null) {
find(k.getChildLeft(), item);
}
if (!found && k.getChildRight() != null) {
find(k.getChildRight(), item);
}
return k;
}
Running the debugger I can see, that when I search for an item that exists in the tree, it will find the correct node and go to the first return statement after "found" is set to true.
However, then compiler doesn't return that Node to the method call, but goes on to the second return statement, returning the root. So no matter where the Node is located, the method will always return the root.
What am I doing wrong?
Your method never returns "not found" which is fundamentally wrong because most of the times an item is not in the data. And that is your main problem. You need to return null / an empty Optional in the bottom return statement. And then you need to properly handle that "not found" return value when traversing the tree downwards, namely where you call find for the left and right child.
Your logic has to always be:
has the current node the correct value
if yes return the current node
does the left node contain the value
if yes return the corresponding node from the left
does the right node contain the value
if yes return the corresponding node from the right
return "not found" (because the current node is not correct and neither the left nor the right contain the value)
You currently skip / have not implemented the two nested "if yes return the corresponding node from the left/right" code paths.
(and of course remove the found variable as noted in a comment)
public BinNode find(BinNode k, Comparable item) throws NullPointerException {
if (k.getData().equals(item)) {
return k;
}
if (k.getChildLeft() != null) {
BinNode node = find(k.getChildLeft(), item);
if (node != null) return node;
}
if (k.getChildRight() != null) {
BinNode node = find(k.getChildRight(), item);
if (node != null) return node;
}
return null;
}
You need to return the finds from the left and right calls.
Your code finds the node and returns the k, but the other finds make no returns so your code continues on with code after the conditional statements, which is to return the node k. However, this falls back through the return stack to the original call to the double argument find, which has root as the BinNode given, so that is what is returned.
Refer Luk2302 answer.
You forgot "return" for left and right calls for find() function.
if (!found && k.getChildLeft() != null) {
return find(k.getChildLeft(), item);
}
if (!found && k.getChildRight() != null) {
return find(k.getChildRight(), item);
}

Level order traversal in a binary search tree in java

I have made 4 different traversals for my binary search tree. I am stuck at the last one which is the level order traversal and I can't get seem to find out how to do it correctly.
The main problem is that I don't know how to only search one level at a time, I only can figure out how to search either the whole left or whole right subtree.
private void preOrder(BinaryNode<AnyType> t )
{
if(isEmpty()){
System.out.println("Empty");
}
if(t != null) {
System.out.println(t.element);
preOrder(t.left);
preOrder(t.right);
}
}
private void postOrder(BinaryNode<AnyType> t){
if(isEmpty()){
System.out.println("Empty");
}
if (t != null) {
postOrder(t.left);
postOrder(t.right);
System.out.println(t.element);
}
}
private void inOrder(BinaryNode<AnyType> t)
{
if(isEmpty()){
System.out.println("Empty");
}
if (t != null) {
inOrder(t.left);
System.out.println(t.element);
inOrder(t.right);
}
}
private void levelOrder(BinaryNode<AnyType> t, int level)
{
if(isEmpty()){
System.out.println("Empty");
}
if(height(t) == 2) {
System.out.println(t.element);
}else if(height(t) > 1){
levelOrder(t.left, level );
levelOrder(t.right, level );
}
}
This is how I did it.
private void levelOrder(BinaryNode root) {
if (root == null) {
return;
}
Queue<BinaryNode> q = new LinkedList<>();
// Pushing root node into the queue.
q.add(root);
// Executing loop till queue becomes
// empty
while (!q.isEmpty()) {
BinaryNode curr = q.poll();
System.out.print(curr.element + " ");
// Pushing left child current node
if (curr.left != null) {
q.add(curr.left);
}
// Pushing right child current node
if (curr.right != null) {
q.add(curr.right);
}
}
}
Your approach looks like DFS approach It may not follow that approach.
Try to use Queue here it will help you traverse correctly.
Because it will follow BFS approach so that you can traverse level by level.
Add first left node then right node and according follow.
View the entire search as a sequence of "rounds", one "round" for each level.
In each round :
- initialize a "next round" list of nodes to empty
- process a prepared list of nodes (the ones that are at that level and thus to be searched in that round) whereby for each node :
- do the actual comparison
- add all the node's child nodes to the "next round" list
Start the process with a "next round" list populated with just the root node.
Repeat until the list of "next round" nodes comes up empty or you found what you were looking for.

Recursion of Linked List

When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}

null pointer exception while searching linked list [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I created a search method for a linked list. It works correctly when I search for something that does exist in the list. If I search for something not in the list, then I get a null pointer exception.
I don't see how its possible to get this exception.
Here is the method:
// these two search methods return the node containing the substring given
public UNode search(String cityName)
{
return search(cityName,this);//line 90
}//end search()-------------------------------------------------------------
private UNode search(String cityName, UNode current)
{
if(current != null)
{
if (current.getCity().getName().contains(cityName))
{
System.out.println("Node '" + current.getCity().getName()
+ "' has been found and returned.");
return current;
} else
{
return search(cityName,current.next);//line 105
}
}
else
{
System.out.println("No node containing the substring '"
+ cityName + "' can be found, returning null");
return null;
}
}//end search()-------------------------------------------------------------
To my understanding, this is what happens when searching for something that does not exist: The method keeps calling search() recursively with current.next, it gets to the last element and calls search(cityName, null), then since current is null, it says it is not found, and returns null.
Am I missing something here? What am I doing wrong? Should I just throw the null pointer exception?
Here is the method where I call the search method:
public static void uNodeTest(City[] cities)
{
UNode unvisited = new UNode();
unvisited.addCities(cities);
String a = unvisited.getNext().getNext().getNext().getCity().getName();
System.out.println(a);
UNode current = unvisited;
while(current.getNext() != null)
{
System.out.println(current.getCity().getName());
current = current.getNext();
}
UNode phil = unvisited.search("not a city");
}
Stack Trace:
java.lang.NullPointerException
at cityproject.UNode.search(UNode.java:105)
.
.
.
at cityproject.UNode.search(UNode.java:105)//(omitting repeats)
at cityproject.UNode.search(UNode.java:90)
at cityproject.CityProject.uNodeTest(CityProject.java:104)
at cityproject.CityProject.main(CityProject.java:79)
I would add a check before calling the recursive search to see if current.next is null:
if(current.next != null) {
return search(cityName,current.next);
}
else {
return null;
}
This might solve the null pointer exception...

Categories