Infinite recursion in Java with splay trees - java

I am trying to write a "contains" method for a splay tree to figure out if a node is already in the tree. I give this method a node to start searching and a string key to use find the corresponding node. I think I have a pretty good handle on recursion, but I am stumped by this. I've bolded the two lines that are causing the infinite recursion, but I'm stuck because, unless you somehow have a tree with an infinite number of elements, wouldn't the left and/or right elements have to be null at some point? They cannot be != to null forever! I might be losing my mind but I would very much appreciate any clarification on how to create a stronger base case.
tldr: how is it possible for this function to recurse infinitely when we have to run into null at some point?!
public BST_Node containsNode(BST_Node node, String s) {
BST_Node result = null;
if (node == null) {
return null;
}
if (node.data.compareTo(s) == 0) {
splay(node);
return node;
}
if (node.left != null) {
result = containsNode(node.left, s); //recursion here
}
if (result == null && node.right != null) {
result = right.containsNode(node.right, s); //recursion here
}
return result;
}
}

Related

Java Recursion iterator with my own tree

I have two pieces of code that in my mind do the same thing but it doesn't.
I am trying to create an iterator for my custom set tree. Here's the code.
public LinkedList<AnyType> traverse (TheNode<AnyType> node,LinkedList<AnyType> theList){
if (node.left != null)
return traverse (node.left,theList);
theList.push(node.element);
if (node.right != null)
return traverse (node.right,theList);
return theList;
}
public void traverseNrTwo (TheNode<AnyType> node){
if (node.left != null){
traverseNrTwo (node.left);
}
list.push(node.element);
if (node.right != null){
traverseNrTwo (node.right);
}
}
traverse only goes through the left side of the tree and adds it to the list but traveseNrTwo goes through the whole tree. So, my question is, why do they do two different things?
You shouldn't return the result of the recursive calls, since it causes the recursion to visit just the left side of the tree.
public LinkedList<AnyType> traverse (TheNode<AnyType> node,LinkedList<AnyType> theList){
if (node.left != null)
traverse (node.left,theList); // if you return traverse(node.left,theList) here,
// you end the recursion without adding the current
// node and visiting the right sub-tree
theList.push(node.element);
if (node.right != null)
traverse (node.right,theList);
return theList;
}
Also note that since you are passing the LinkedList<AnyType> as an argument to your method (i.e. you are not creating a new LinkedList instance inside your method), you don't have to return it. You can simply change the return type to void.

NullPointerException in a while loop using a Binary Tree node

I am using a binary tree structure here. I am getting a "NullPointerException" from the line containing the while statement. I am completely confused about why that would be.
BinaryTreeNode<CharData> currNode = theTree.findValue(data);
// Move up the Binary Tree to create code.
while(currNode.getParent() != null) {
// The loop does some stuff that doesn't
// affect what is assigned to currNode.
// Move to the parent node for the next iteration.
currNode = currNode.getParent();
} // End the while loop.
return code; // Return the string of binary code.
Find value is a method from my BinaryTree class that searches for and finds the node containing specific data. I know this works from testing it separately outside of this implementation.
The only reason why the while-loop statement can throw a NPE is, when currNode is null. I suspect findValue() returned null.
I guess one fix (when you care about the topmost node) would be:
while(currentNode != null) {
rootNode = currentNode;
currentNode = currentNode.getParent();
}
Or the typical pattern which relies on boolean shortcut evaluation:
while(curentNode != null && currentNode.getParent() != null)
Or my prefered solution using guards:
if (currentNode == null)
throw NotFound(); // or return something
while(curentNode.getParent() != null) {
If you see the code:
BinaryTreeNode<CharData> currNode = theTree.findValue(data);
I guess, currNode is getting some value if findValue() able to search data else it is returning NULL values.
When it returns a NULL value it will throw NPE.
To avoid it, you can modify your code a little bit.
while(currNode != null && currNode.getParent != null) {
// your code here
}

Recursively searching a Binary Tree for string values

I've got a binary tree that should only hold unique string values. Prior to entering a new string (which is done by the user), I need to recursively check the tree to see if the string already exists. Here's the method I've come up with, but it's only finding certain values (the root and the left ones I believe). Any tips on how to fix this are appreciated!
public static TreeNode wordExists(TreeNode root, String strInput){
if (root != null){
if (strInput.equals(root.dataItem))
{
return root;
}
if (root.left != null){
return wordExists (root.left, strInput);
}
if (root.right != null){
return wordExists (root.right, strInput);
}
}
return null;
}
When you navigate down each branch, you need to check the result before returning it. Otherwise, if the result is only in the right branch, but there are other, non-null values in the left, you'll just return null, since it isn't found in the left path.
So instead of
if (root.left != null) {
return wordExists(root.left, strInput);
}
if (root.right != null) {
return wordExists(root.right, strInput);
}
you might do something like
TreeNode result;
if ((result = wordExists(root.left, strInput)) != null) {
return result;
}
return wordExists(root.right, strInput);
You can get away with the shortcut on the second recursion, since, if it fails, you'll just be returning null anyway.

Java : Merging two sorted linked lists

I have developed a code to merge two already sorted linked lists in java.
I need help with the following:
How do I retain the value of head node of merged list without using tempNode?
Can this code be better optimized?
public static ListNode mergeSortedListIteration(ListNode nodeA, ListNode nodeB) {
ListNode mergedNode ;
ListNode tempNode ;
if (nodeA == null) {
return nodeB;
}
if (nodeB == null) {
return nodeA;
}
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode = nodeA;
nodeA = nodeA.getNext();
}
else
{
mergedNode = nodeB;
nodeB = nodeB.getNext();
}
tempNode = mergedNode;
while (nodeA != null && nodeB != null)
{
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode.setNext(nodeA);
nodeA = nodeA.getNext();
}
else
{
mergedNode.setNext(nodeB);
nodeB = nodeB.getNext();
}
mergedNode = mergedNode.getNext();
}
if (nodeA != null)
{
mergedNode.setNext(nodeA);
}
if (nodeB != null)
{
mergedNode.setNext(nodeB);
}
return tempNode;
}
1: You have to keep a record of the first node, which means you will have to store it in a variable such as tempNode.
2: No. There's not much to optimize here. The process is quite trivial.
There are a few possibilities:
1) Instead of using mergedNode to keep track of the previous node, use nodeA.getNext().getValue() and nodeB.getNext().getValue(). Your algorithm will become more complex and you will have to deal with a few edge cases, but it is possible to eliminate one of your variables.
2) Use a doubly linked-list, and then use either nodeA.getPrev().getValue() and nodeB.getPrev().getValue() instead of mergedNode. You will also have to deal with edge cases here too.
In order to deal with edge cases, you will have to guarantee that your references can not possibly be null before calling getPrev(), getNext() or getValue(), or else you will throw an exception.
Note that the above modifications sacrifice execution time slightly and (more importantly) simplicity in order to eliminate a variable. Any gains would be marginal, and developer time is far more important than shaving a microsecond or two off of your operation.

Trying to create a removeLastElement using recursion

I need to make a method that removes the last element of a LinkedList using recursion.
This is what I have so far but it doesn't seem to be removing the node...when i call list.size() it is still the same size with the same values. What am I doing wrong here?
This is for Java by the way
public void removeLastElement(Node curr){
if (curr == null)
return;
else{
if(curr.next == null)
curr = null;
else
removeLastElement(curr.next);
}
}
In a LinkedList to remove the last element you have to get the penultimate element and set
curr.next = null
You're in the right way to get the recurrent function to remove the last node. The problem is you're identifying the penultimate node with curr.next == null, if you got it, you nullify it, but that's your actual input! So, you must check if the actual node is the antepenultimate node on the list:
if (curr.next.next == null) {
curr.next = null; //Now you're modifying the data in your input.
}
With this change, there are more basic cases to check, but that's up to you, my friend.
Boolean deleteLast(Node n)
{
if(n.next == null)
return true;
if(deleteLast(n.next))
{
n.next = null;
return false;
}
return false;
}
Node deleteLast(Node n) {
if (n.next == null)
return null;
n.next = deleteLast(n.next);
return this;
}
The general idea is you ask the next node "hey, can you tell me where you are, and delete your last node?" The last node can then just say "I'm nowhere" and it'll all fall into place.
This is very similar to Aadi's answer, just using Nodes instead of booleans.

Categories