Java recursive binary tree - java

Welcome!
I have a recursive public static method named less that takes a tree node (an original binary tree, not really a search tree) and a int parameter that returns if all the values in the tree are less than the integer. So, I would use a public class TN { public int value; public TN left, right; public TN(int v, TN l, TN r) {value = v; left = l; right = r;} }
So, my method would look like this:
public static boolean less(TN s, int toFind){
if (s == null)
return true;
else{
if(s.value <= toFind)
return less(s.left, toFind) && less(s.right, toFind); // right here do I return true? or do I have to somehow recall recursively
else
return false;
}
I was wondering if that was right or am I missing something??? Do I have to return true and false??

There are much more elegant, OO ways to write this. My recommendation would be to make less() a non-static member function of the TN class. That way, if the tree's root node is called root, you just call root.less(). Each call to less() will then call left.less() and right.less().
Since you posted example code that wouldn't even compile, I'm wondering if you're using an IDE, or even tried to compile your class using javac. I strongly recommend getting Eclipse, Netbeans, or another IDE if you're new to Java.

return less(s, toFind);
should be:
return less(s.left, toFind) && less(s.right, toFind);
I don't know why the function is static.
As mentioned before, your first part should just be:
if (s == null) return true;
(EDIT: This will let you get a true result when all nodes meet the condition. You have an == in there that should be a <).
EDIT: Ok, you've got a lot of problems than just those I mentioned. You need to logically step through your code.
You need to traverse your tree, so you'll need to call your function on your children nodes. Next, you need to return true as your default result. That way, when you reach a number greater than what you're looking for, you can return false immediately without traversing any of the children. I hope I've helped you enough with the logic for you to get through the rest of it yourself.

First, if (s = null) should be if (s == null) as you are doing a comparison, not setting the value of s to null.
The statement return less(null, toFind); keeps calling your method - you'll overflow your stack.

Notice how there's no way that your function could ever return true because every time you terminate the recursion, you're returning false? And the problem is in your first check. You say that "all the values in the tree are less than the integer." Well, in an empty tree, all the values (of which there are none) are indeed less than any integer, so you should return true in that case.
Also, while you say "less than", you're comparing for equality, so you're actually checking whether all the values are equal to the integer, not less than it.

Related

Homework: Return the least element in the set greater than given element BST

So I've been stuck for hours trying to figure out this problem.
Given a randomly generated BST and using the method header:
public E higher(E elt)
Where elt is a randomly generated value within the tree's range, I need to find the least element in the set greater than elt.
Nodes contain left links and right links, but no parent link.
The tree in the linked image reads with the root being the leftmost node
BST.
So if elt is 27, then I want to return the node containing 28.
I need to run this in O(logn) time, and everything I've tried has not worked.
I'm not looking for someone to do my homework for me, but I have no clue what to do at this point.
I can provide more detail and source code if it's needed.
Edit: I'll put this here, though it's woefully inadequate. I feel as though this would be easier if I could do this recursively but I can't think of a way to do that.
Node n = root;
//need to get this into a loop somehow and break out when I've found
//the right value
int c = myCompare(elt, ((E) n.data));
if (c < 0) {
n = n.left;
//now I need to compare this against any children
} else if (c > 0) {
n = n.right;
//now I need to compare this against any children
}
return ((E)n.data);
This depends on the fundamental property of BSTs: the left child is less than the parent, the right child is greater than the parent. If you look at a sample BST you will quickly notice a few properties, and you can see why the following algorithm will work.
If the current node is less than the given value, move right, otherwise move left. If you reach a point where moving left will give you a value that is too low (or you hit a leaf) then you found the correct node. Or, in pythonic pseudo-code:
while (true):
if (node.value <= elt):
node = node.right
else:
if (node.left.value < elt):
return node.value
else:
node = node.left
The pseudo-code obviously needs to check for errors, if a node is a leaf, etc., but this general algorithm will give you the expected output in the desired time complexity (assuming a balanced BST).
One possible approach is to find the specified node and to get the next least node from there (if you're allowed to use helper methods).
If we say that the root node is 'n' and we know that the desired value is inside the BST, then you can traverse through it to find the node that contains the given value with something like this:
public Node search(Node n, E obj)
{
if(obj.compareTo(n.getValue()) > 0)
{
return search(n.getRight(), obj);
}
else if(obj.compareTo(n.getValue()) < 0)
{
return search(n.getLeft(), obj);
}
else
{
return n;
}
}
If the objective were to retrieve the least value from a binary search tree, a simple recursive method like this would work:
public Node getLeast(node n)
{
if(n.getLeft()==null)
{
return n;
}
return getLeast(n.getLeft());
}
Using the principles of a binary search tree, we know that the least value greater than a given node is just the least node after the right child of the given node. So, we can just use this method to obtain the desired value:
getLeast(search(n,elt).getRight());

Implementing an equals method recursively

Basically, I need to compare two arrays and check if they have the same values in the same positions (recursively of course). I get an error with my current code: Array out of index exception:20
The code I have right now looks as follows:
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd){
if (first[iStart] == second[iStart]){
if (equalsHelper(first,second,(iStart+1),iEnd))
{
return true;
}
}
if (iStart == iEnd){
return first[iEnd] == second[iEnd];
}
return false;
}
You simply need to put you stop condition at the begin of you code. This will work if iStart is 0 at the beginning and iEnd is array length - 1.
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) { // you need to check this first
return first[iEnd] == second[iEnd];
}
if (first[iStart] == second[iStart]) {
if (equalsHelper(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
If you want to use the array length as input for iEnd you just need to change the code a little
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) {
return true;
}
if (first[iStart] == second[iStart]) {
if (equalsHelper2(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
Since performance was mentioned a few times I will say a few things about it.
The stack contains information about local variables and function calls. So each recursiv call will save these informations on the stack which will lead to a stackoverflow on huge inputs since the stack only has limited space. It is also slower in terms of execution due to more assembler commands in comparison to loops.
This can be avoided by using tail recursive functions.
A tail recursive call means simply that your recursive call must be the last statement that is executed in your method. The compiler will translate this into a loop. This is faster and uses less space on the stack.
A tail recursive version of your equals method would look like this:
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd)
{
if (iStart == iEnd)
{
return true;
}else{
if(first[iStart] != second[iStart])
{
return false;
} else
{
return equalsHelper2(first, second, iStart + 1, iEnd);
}
}
}
Leaving aside the question of whether recursion is the right solution (it really isn't, iteration here is trivial and will perform better), the problem is that the termination condition (iStart == iEnd) is not checked until after the recursive call.
Any recursive algorithm must a) check whether it is appropriate to continue recursing, and b) do the recursive call after that check. Failing to include the first step, or doing the steps out of order, will result in infinite recursion until an error is reached (StackOverflowError if nothing else happens first).
You do have a condition check before your recursive call, but it's for the method's overall purpose rather than for ending recursion. You also have a condition check for ending recursion, but it's done after the recursive call. The solution is to swap their order - take the if (iStart == iEnd) block and move it to before the if (first[iStart] == second[iStart]) block.
Recursion is a powerful programming technique, but has some draw backs in the Java language. If a method in java calls itself recursively an excessive number of times before returning it will lead to a StackOverflowError. It this instance, comparing equality of two Array's is almost guaranteed to do so.
Other languages like Scala allow you to write recursive functions which are optimised for recursion (tail recursive) and execute in constant stack space.
That been said, you should think whether recursion is really the correct solution here. It neither optimises the solution, nor adds code clarity.
Note: If you just want to compare two Array's in Java, then java.util.Arrays already has you covered.

How Do You Make A Recursive Boolean Method Of "isSubstring(str1, str2)"

if (isSubstring(str1, str2))
System.out.println(str1 + " is a substring of " + str2 + ".")
and here is the method for isSubstring:
public static boolean isSubstring(String str, String target)
{
if (str == target)
return true;
return (isSubstring(str, target.substring(0,5)));
}
That is what I have in code right now and I can't fathom how you would go about solving this. My instructor is requiring us to use recursion so the return MUST call itself. Normally this problem could EASILY be done with only one line of code:
public static boolean isSubstring(String str, String target)
{
return str.contains(target)
}
But I must pointlessly use recursion to solve this and it is EXTREMELY frustrating knowing how trivial this method is and how overly complicated my instructor is forcing us to do this. I don't really know where to start because "return str.contains(target)" doesn't give me a good foundation for how I could try solving this.
A couple things:
First, you have the right idea, but you want to make the 'next' string you search one size smaller than your current string. So if you were looking in the string Hamburger, you'd search amburger second, then mburger. So when you recur, you might try something like return isSubstring(str,target.substring(1)) Right now you appear to be using the number 5 as to take the first 5 characters. That's strange because the first time you do it, (Hamburger to Hambu) you won't ever be able to do it again. And if your original target was "ham" then you'd bomb immediately! Not so good.
Second, it's not enough to test if it's equal. Using the hamburger example, if you were looking for urge, you'd find urger and then go right to rger. You wouldn't ever get urge. So instead of testing for equals, test with beginsWith() instead. (If you were shrinking it from the back, like Hamburger to Hamburge to Hamburg, then you'd use endsWith().)
Lastly, you don't have a good path for what to do if you don't reach the goal. If you have xyzzy for a target, and you're searching for bob, you won't find it. So you need a "base case", which I recommend using as the first line. Something that says "if it would be impossible for the token to be in the target, then let's return false right away".
It's hard and its frustrating, and it seems pointless. But keep in mind he's not trying to teach you to search strings. That's silly, you know how to search strings! He's trying to teach you recursion, which is not easy to "get".
One fix is: Use equals() instead of == while comparing String/Objects. == compares reference equality. equals() compares for content equality.
if (str == target)
should be
if (str.equals(target))
Okay I got it, Asad's advice was useful. Here is a working method for isSubstring:
public static boolean isSubstring(String str, String target)
{
if (target.length() == 0)
return false;
if (str.equals(target))
return true;
else
return (isSubstring(str, target.substring(0,target.length()-1)));
}
I'm not sure if the second "if" should be an "else if" instead.
Compare strings with the equals() method: change
if (str == target)
to
if (str.equals(target))
You know that the function applied to:
base case) An empty string, must return false;
base case) A string starting with the once you are looking for, must return true;
rec case) Else remove the first character and check the rest of the string.
Here the code in Java:
public static boolean isSubstring(final String str1, final String str2) {
if ((str1 == null) || (str2 == null) || str1.isEmpty()) {
return false;
} else if (str1.startsWith(str2)) {
return true;
} else {
return isSubstring(str1.substring(1), str2);
}
}
Test:
public static void main(final String[] args) {
System.out.println(isSubstring("hello this is a simple test", "is a"));
}
Output:
true

DFS tree traversal function modification

Please find below my implementation for DFS.
protected void DFS(String search) {
for(Tree<T> child : leafs) {
if(child.value.equals(search))
return;
else
child.DFS(search);
System.out.println(child.value);
}
}
The objective is to stop traversal on finding the node whose value is in the variable search. However, the above function goes on traversing the tree even beyond the declared search node. Could someone help me modify the above function?
Thank you.
Edit 1
protected boolean DFS(String anaphorKey) {
boolean found = false;
for(Tree<T> child : leafs) {
if(child.head.equals(anaphorKey))
return true;
found = child.DFS(anaphorKey);
if(found == true)
break;
System.out.println(child.head);
//System.out.println("anaphorKey: "+anaphorKey);
}
return found;
}
Tried implementing the given answer suggestion (#SJuan76). The implementation above isn't working as desired. Could you point me to the place where code is not as per the logic suggested?
rookie, might I suggest an implementation using the classic for-loop (as opposed to the enhanced for-loop being used now) which allows integration of your stop-condition a bit better, something like:
protected boolean DFS(String key) {
boolean found = false;
for(int i = 0; i < leafs.size() && !found; i++) {
Tree<T> child = leafs.get(i);
if(child.head.equals(key))
found = true;
else
found = child.DFS(key);
}
return found;
}
So as soon as your found condition is hit, the 'found' becomes true and your loop stops.
What you may have forgotten is the "found = child.DFS(key)" portion of the recursion, where you need to remember the result of your recursive calls so ALL your for-loops on up the chain all break as soon as you return.
Hope that helps.
Option A (Nice): the function returns a value, when the node is found it returns a different value that if the node was not found. When you call to method, if you get the found value you stop the loop and return the found value too.
Option B (Ugly): When found, thow an Exception (better if it is your own implementation of it). Don't forget to catch it.
Option C (Uglier): The same with global (static) variables.
UPDATE 1:
It looks like your method should run ok now, can you check (System.out.println) if your value is ever found?
In a more personal opinion, I would find
protected boolean DFS(String anaphorKey) {
for(Tree<T> child : leafs) {
if(child.head.equals(anaphorKey))
return true;
if(child.DFS(anaphorKey)) // No need to store value. No need to check == true (it is implicit)
return true; // If we are in this line the value was found, always return true
System.out.println(child.head);
//System.out.println("anaphorKey: "+anaphorKey);
}
return false; // If the method did not exit previously it was because the value was not found, so in this line always return false
}
more readable (but it should work exactly as your implementation)

Searching for a node in a tree in Java

I have a binary tree made with the following constructor:
public Person(String name, int age, char gender, Person c1, Person c2)
where c1 is the left child and c2 is the right child.
I want to write a method that searches for a particular name within a maximum generation. So like a.depthFirstSearch(Eva, 1); where Eva is the name to search for and 1 is the maximum number of generations (or levels) I can look into.
Here's what I have:
EDIT:
public Person depthFirstSearch(String name, int maxGeneration)
{
{
Person temp;
if (maxGeneration>1){
if (this.name.equals(name)){
temp=this;
return temp;
}
else{
if (child1!=null)
temp=child1.depthFirstSearch(name, maxGeneration-1);
if (child2!=null)
temp=child1.depthFirstSearch(name, maxGeneration-1);
}
}
return null;
}
}
There's two problems here. I think depth gets reset to 0 every time the function calls itself, so I know I can either keep track of depth somewhere else or find an alternative. The other problem, I think, is that child2 is never really reached, since I return at child1. I'm not really sure how this works so if someone could explain that, that'd be great. Any suggestions for some fixes?
Also, I'm told that I have to search depth first, meaning looking into the deeper generations first. I'm not really sure what that means and how different it is from the logic I'm using in my implementation.
Since you decrement maxGeneration in each recursive call, you don't need the depth variable at all: when maxGeneration == 0 you simply don't search any more and return null.
As for your other problem, instead of directly returning the value of child1.depthFirstSearch(...), store the value in a temporary variable. If it is not null, you have found the node, so return it immediately, otherwise continue searching under child2.
Update:
It should be if (maxGeneration >= 1) ... (greater than or equal to), otherwise the last call with maxGeneration == 1 will always return null. Alternatively, you can just check for 0 and return null:
if (maxGeneration == 0)
return null;
// rest of your code
Also, you still aren't using the return value to check if the node was actually found in the left subtree or not. Right now, even if you find the node under child1, you still look under child2 and you will end up returning null, which is wrong. You need to search under child2 only if the left search returned null:
Person temp;
if (child1 != null) {
temp = child1.depthFirstSearch(name, maxGeneration-1);
if (temp != null)
return temp; // found the node, just return
}
// otherwise the following code will execute
if (child2 != null) {
temp = child2.depthFirstSearch(name, maxGeneration-1);
if (temp != null)
return temp; // found the node, just return
}
// didn't find node under either child
return null;

Categories