Some questions regarding recursion - java

What is direct recursions? What is infinite recursion?
What is a base case and why is it necessary/important?
example code:
public static void indifferent(int x, int y) {
if (x <= y) {// base case
System.out.print("!");
}else {
System.out.print(x);
indifferent(x - 1, y + 2);
System.out.print(y);
}
}

Direct recursion is when a method calls itself (as in your example code). Indirect recursion is when method a() calls method b(), which itself (either directly or indirectly) calls method a() again.
Infinite recursion is recursion that never ends. Another way of putting it is that infinite recursion is when the base case either does not exist or is never encountered.
A base case is a set of argument values that causes the method to return without a recursive call (either direct or indirect).

Direct recursion: Method invokes itself.
Indirect recursion: Method invokes some other method and after many invocations, the call returns, to a situation where the first calling method is invoked again.
Base case: It is an important component of any recursion function. It is a condition for recursive method to stop calling itself and thus end the recursion i.e. stop going deeper in recursion. Basically, if you think of recursion as a yoyo then it is the base case when the recursion is at its extreme end.
infinite recursion: It is a recursion which never ends. Basically it is a recursive function which does not have a base case. (a yo-yo which doesn't come back and goes all over the place.)
Checkout these interesting recursion images at this link

Here's an algorithm for climbing stairs
climb:
if you are at the top
stop
otherwise
step up and then climb
That shows you direct recursion (climb is a step inside climb) and base case (stop if you are at the top).
Two cases of infinite recursion:
climb:
step up and then climb
climb:
if you are at the top
stop
otherwise
step up and then step down and then climb
The first has no base case and the second will never reach the base case:
Finally, indirect recursion:
group climb:
if there's no one in the group
stop
otherwise
step up
step up:
if first in group is at top
remove them from the group then group climb
otherwise
step up first in group then group climb

Related

How to understand a recursive inorder traversal of a BST in Java?

I am trying to understand how the well-established methods of implementing an inorder traversal of a binary search tree are functioning in Java.
I am given the following code:
public void inorder() {
if (!this.isEmpty()) {
this.getLeft().inorder();
System.out.print(this.getValue());
this.getRight().inorder();
}
}
with isEmpty() returning whether the current Node is null, getValue() returning the value of the current node, and getLeft() as well as getRight() respectively returning the left and right successor node.
My problem here is, I do not understand how one is able to process the traversal with this code. I have visualized my chain of thoughts on a sheet of paper for you guys to see, with the circles being the nodes, the black squares being null nodes, and the encircled node being the current (this) object. As I am following the pseudocode, I would land in a null node at the end and hit the recursive dead-end case. I also do not at all understand how the code is able to go back in the tree hierarchy once we've already set subtree nodes as the current this object.
My visualization
Am I imagining this wrong, and if so, could someone help me understand the right way of doing this? The code works, but I really need to understand how that comes through. Any help would be super super appreciated
As I am following the pseudocode, I would land in a null node at the end and hit the recursive dead-end case
When you reach the "dead-end" case, this means the current branch of the recursion tree ends. It doesn't mean the entire recursion ends.
After all, when method X calls method Y, and method Y ends, the control returns to method X. This remains true when methods X and Y have the same name. The recursion only ends after the original inorder() call (which was executed on the root of the tree) returns.
You can number each call to the inorder() method in order to tell them apart:
1. root.inorder() calls
2. root.getLeft().inorder() calls
3. root.getLeft().getLeft().inorder() calls
4. root.getLeft().getLeft().getLeft().inorder()
this node is empty, so inorder() #4 method returns control to the previous one (#3)
now #3 call prints the current node via System.out.print(this.getValue())
which prints the left most node of the tree
then #3 calls
5. root.getLeft().getLeft().getRight().inorder()
this node is also empty, so the current inorder() method returns control to #3
now #3 also ends, and returns control to the previous method (#2)
and so on...

Switch statements - JVM memory allocation, stack overflow

I am taking a Java class in school. We had this assignment to design a class to function as a menu, with several sub menus.
The structure is kinda like this (sort of pseudocode below, just to show structure):
public static void mainMenu() {
switch(integer variable){
case 1: submenu1();
break;
case 2: submenu2();
break;
}
}
public static void submenu1() {
switch(integer variable){
case 1: subsubmenu1();
break;
case 2: subsubmenu2();
break;
default: mainMenu(
}
}
public static void subsubmenu1() {
switch(integer variable) {
case 1: anothersubmenu1()
break;
case 2: anothersubmenu2();
break;
default: submenu1();
}
}
My question is: my teacher said this is wrong, because JVM stores in the memory the path that the program takes from one place to the other if I make it this way, and in the long run this would cause a stack overflow. He didn't quite explained it, he just said that I should surround the whole thing with a while loop using a boolean variable, adding an option to flip that boolean value to exit the while loop, because this way Java wouldn't be storing the path the program was taking from one method to the other.
Again, he didn't explain it with details, and it sounded very confusing the way he was explaining it (I tried to make it as clearly as I could, from what he has given me). I have been looking for the last 3 hours online for anything that resembled what he told me, and I couldn't find anything...so I decided to ask the experts.
Could you guys help me out?
When the computer executes a method/function call, it has to:
Remember what the calling function is doing -- the values of local variables, and where to resume execution when the called function completes;
Transfer control to the called function.
When the called function is finished, it:
Returns control to the remembered position in the calling function; There, it
Restores the values of local variables, etc.; and
Continues processing with the value returned from the called function, if any.
The problem with your system of functions is that they can just keep calling and never return:
mainMenu -> submenu1 -> mainMenu -> subMenu1... etc., etc.
If your functions never return, then it just has to keep remembering more and more stuff each time you make a new call, possibly at some point exceeding the amount of (stack) memory that is available for storing that stuff, resulting in a stack overflow error.
Some languages implement an optimization called "tail call optimization" that will actually avoid storing those things when calling another function is the last thing your function can do. In this case it's not going to need the values of local variables again, and doesn't need to remember where to resume, because it can resume in its calling function, which is already remembered.
In languages like that, your code can actually be OK... but java is not one of those languages.
Yes, your teacher is (partly) correct.
The critical part is that you potentially call mainMenu() from within submenu1() and you call submenu1() from within subsubmenu1().
If you call mainMenu() everytime you are in submenu1() and call submenu1() whenever you are in mainMenu() your program will crash.
For every function call, the underlying system needs to reserve memory for the function's local variables and such. That's the so-called stackframe. It is called recursion when you call a function from within itself (directly or indirectly). Recursion needs to return at some point. If it doesn't you get a stackoverflow because the memory runs out.

Build Binary Tree from Preorder Traversal: Stack Overflow Error

I have a tree where the leaves are marked with L and the non-leaf nodes are marked with I. I am given the preorder traversal of the tree. An example is IIILLILILLIIILLLIILILLL. I have to build the huffman tree for this included string. I originally pass in a new Root(), 0, and my treeString for my arguments. TreeString would be the string with the I's and L's pasted above. For some reason my code causes a StackOverflow exception to be thrown. My code is as follows for the makeTree method:
public static void makeTree (BinaryNodeInterface<Character> root, int start, String treeString)
{
if (treeString.charAt(start)=='L'){
root.setLeftChild(null);
root.setRightChild(null);
return;
}
BinaryNodeInterface<Character> leftSide = new BinaryNode<Character>();
root.setLeftChild(leftSide);
makeTree(root.getLeftChild(), start++, treeString);
BinaryNodeInterface<Character> rightSide = new BinaryNode<Character>();
root.setRightChild(rightSide);
makeTree(root.getRightChild(), start++, treeString);
}
I have no idea what is causing the stackoverflow exception to be thrown. I would think that my base case at the beginning would return and handle it.
I believe this is the problem:
makeTree(root.getLeftChild(), start++, treeString);
I'm not sure what your approach is, but it looks like if you see an I, your plan is to go to the left node, and start examining the string starting at the next character.
The reason for the infinite recursion is that start++ is a post-increment operator, which means that it gives you the current value of start and then increments it. Thus, each time makeTree calls itself, it calls itself with the same version of start, and thus looks at the same I in the input string.
However, changing it to ++start will not make things work. (It might avoid the stack overflow, but it won't work right.) The reason is that when you call makeTree, you want to give it the starting location of the string where you want the recursive call to start looking--but you also want the recursive call to tell it how much of the string it consumed. That is necessary because, after makeTree calls itself recursively on getLeftChild, you will call it again on getRightChild, and you need to call it with the correct starting point.
Note that each recursive invocation has its own copy of start. Thus, when makeTree calls itself, and the second makeTree increments start, this has no effect on the start that the first makeTree sees.
You'll somehow need each recursive makeTree to tell its caller how much of the string it consumed. Probably, the simplest way to do this is to change the return type to int; you can decide whether you want the function result to be the number of characters consumed, or the index where it stopped scanning, or something similar. Then, after calling makeTree recursively, use the function result to adjust the start parameter. Make sure makeTree returns the correct result, both in the leaf and the non-leaf cases. Be careful to avoid off-by-one errors.
You cannot create a tree just from preOrder list.
Atleast you need inorder traversal as well OR if is full tree then you can also use posrorder.

Getting the number of the order of the function in a recursive call

What is the easiest way to retrieve the order of the function in a recursive call. For instance, if we have a recursive function, it keeps calling itself until it finds the base case, and then it returns one function at a time. The first function returning is of order 0, the second is of order 1, and so on...What is an easy way to retrieve the order information? Say for instance, when it is the function of order three, I would like to do something special.
Edit: I want the function at the top of the stack to be zero.
Edit2: The problem I am trying to solve is to return the nth element of the in order traversal of a binary tree.
If you are starting with a recursive function that looks like this
void recursive(int p1, String p2, long p3) {
...
if (someCondition) {
recursive(nextP1, nextP2, nextP3);
}
}
change it to this:
void recursive(int p1, String p2, long p3, int level) {
...
if (someCondition) {
recursive(nextP1, nextP2, nextP3, level+1);
}
}
Now Start off the level at zero by calling
recursive(initialP1, initialP2, initialP3, 0);
level will indicate the number of invocation of recursive above you.
EDIT : (zero-at-the-top)
You can also transform the function to return its level to implement the "zero at the top" strategy:
int recursive(int p1, String p2, long p3) {
if (baseCase) {
return 0;
}
...
int level = 0;
if (someCondition) {
level = 1+recursive(nextP1, nextP2, nextP3);
}
return level;
}
Note that in this case you cannot find your level until after the last recursive invocation has returned.
The case dasblink has offered you covers the opposite of what you suggested implementation-wise because the level counter rises (increments) as you go deeper in the recursion.
If you want it to decrease as you go deeper in the recursion that would imply that you know the exact recursion depth beforehand.
In most cases if you know the exact recursion depth you won't be using recursion, you'll be using a loop (for, while, repeat/until etc.). In fact using recursion in such a case is less optimal because of the recursion stack that gets allocated (higher memory consumption) and loops are much more efficient.
If the level 0 should be the last "nested call", then it is in general
undecidable problem similar to the halting problem, because you can't
just say "after 3 more nested calls, the function will return a
value". It is possible to look ahead only by simulating the
computation of the particular function.
If the level 0 should be the first call, then it is quite simple and you can use the level as a param of the method and increment it.
btw, interesting problem, see http://en.wikipedia.org/wiki/Halting_problem

Recursion Question : Revision

My slides say that:
A recursive call should always be on a smaller data structure than the current one
There must be a non recursive option if the data structure is too small
You need a wrapper method to make the recursive method accessible
Just reading this from the slides makes no sense, especially seeing as it was a topic from before christmas!
Could anyone try and clear up what it means please?
Thank you
A recurssive call should always be on a smaller data structure than the current one
In general this isn't true but if you are talking about linked lists manipulation with recursion it is. What it is implying is that you need to always be working towards a solution and this usually is dealing with a smaller problem than you started with.
Take for example Quicksort. Each time the function is called it is working with a smaller set of data.
Taking another example of printing a linked list, the next time you call the recursive function the argument should be the tail of the linked list (This code has an error in it, but that leads us to our next point)
void printList(List l){
print(l.head);
printList(l.tail);
}
There must be a non recurssive option if the data structure is too small
This means there should be a base case. The point where the function stops calling itself again.
int factorial(int n){
if ( n == 1 ){ //the base case is when n = 1
return 1;
}
return n*factorial(n-1);
}
Going back to the example of printing a linked list, there has to be a case where you only have an empty list left (in which case the function should do nothing). Going back to the code to print a linked list
void printList(List l){
if ( l.empty == true ){ //the base case is when the list l is empty
return;
}
print(l.head);
printList(l.tail);
}
You need a wrapper method to make the recurssive method accessible
I don't know Java, and it isn't really a language designed for recursion, however in many cases your recursive function will have more parameters than the person using the API should be able to see. You might for example want to have a counter in there.
You can have a wrapper function that simplifies the parameters to just what is needed. The wrapper function then calls the real worker function.
An example might be if we have a linked list class that has the recursive function to print the list. Its declaration would look something like this:
void printList(List l);
However as it is a class method, to someone using the API it doesn't make much sence to have to do this:
myList.printList(myList);
So a wrapper function could be created that doesn't have any paramters which then calls the code that does the work.
void printList(){
doPrintList(this); //pass in the List object as the first argument
}
Then all the programmer using the API has to do is:
myList.printList();

Categories

Resources