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.
Related
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);
}
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;
}
}
So the exercise I am trying to do is:
Write a recursive function to increment by one the value for every node in the binary tree pointed at by "root" then return the modified tree. Assume that nodes store integer values. (-1 means a NULL pointer)
The code I have so far is:
public BinNode BTinc(BinNode root)
{
if (root.right == null && root.left == null){
root.setValue(root.value() + 1);
return root;
}
if (root.left != null) {
root.left.setValue(root.left.value() + 1);
return BTinc(root.left);
}
if (root.right != null) {
root.right.setValue(root.right.value() + 1);
return BTinc(root.right);
}
return root;
}
The problem I am having so far occurs when the root being passed in is -1, in which I get a null pointer exception. I am a bit confused on how this is happening. Is it because I am trying to access the right and left pointers of the null pointer?
in which I get a null pointer exception. I am a bit confused on how
this is happening
you cannot just perform root.setValue(root.value() + 1); because what if the root is null?
you'll need to check if root is not equal to null prior to performing root.setValue.
if (root != null && root.right == null && root.left == null){ // if both left and right nodes are null then simply return root
root.setValue(root.value() + 1);
return root;
}
it's then up to you to set the appropriate value for the root.
Actually, you don't need to check if the left or right node is null or not, it's inefficient. "You do not look at the children to decide whether to make a recursive call." Just access the root and add value and leave the recursive call to do the rest.
public BinNode BTinc(BinNode root){
if (root != null) {
root.setValue(root.value() + 1);
BTinc (root.left());
BTinc (root.right());
}
return root;
}
I am unsure as to what I need to do to search for a string stored in a binary tree. I have the search method written but I don't quite understand what to pass it. I need to search for the string before adding it to the tree. If it is found, I just need to increase the counter within the node object rather than adding a new one. The tree is unsorted by the way.
My question is how do I search for it before adding it?
System.out.println("Enter string to be stored");
stringValue = k.nextLine();
if (theString.isEmpty() == true) {
node.add(stringValue, count);
} else {
// I am not sure what to do here
// How do I send the string to my search method?
stringValue.treeSearch();
}
public Node treeSearch(String s, TreeNode root){
if(root.toString().equals(s)){
return root;
}
if(left != null){
left.treeSearch(s, root.left);
if(root.toString().equals(s)){
return root;
}
}
if(right != null){
right.treeSearch(s, root.right);
if(root.toString().equals(s)){
return root;
}
}else{
return null;
}
}
I update the search method to this.
public Node treeSearch(String s, Node root){
if(root.toString().equals(s)){
return root;
}
if(left != null){
left.treeSearch(s, root.left);
return root;
}
if(right != null){
right.treeSearch(s, root.right);
return root;
}else{
return null;
}
}
There is a bug in the the way you search the left and right subtrees. For example:
if (left != null) {
left.treeSearch(s, root.left);
if (root.toString().equals(s)) {
return root;
}
}
So ... you search the left subtree, but ignore the result of the search and compare s against root ... again.
The same pattern is repeated for the right subtree.
(Since this smells like a "learning exercise", I'll leave you to figure out the fix.)
Having said that, if you don't order the elements of a binary tree, it is pretty much useless as a data structure. You would be better off storing the elements in a list or array. (The complexity of your treeSearch is O(N) ... just like searching a list or array.)
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.