1

I'm new to java programming, and our teacher taught us the concept of recursion and I found it to be a bit complicated. All I understood that it works like a loop(like the factorial of 4) but I still don't quite get it why it works like that. Can I get a detailed explanation on this topic? Here is the piece of code and a picture my teacher used to explain.

package javaapplication1;

public class JavaApplication1 {

static int factorial(int n){
    int t;
    if(n == 0){
        return 1;
    } else {
        t = factorial(n - 1);
        return n * t;
    }
}
public static void main(String[] args) {
    System.out.println(factorial(5));
    }
}

In the following image, the blue color represents stack winding, and the green is stack unwinding, and again I don't know what stack winding and unwinding is.

https://i.stack.imgur.com/pjqJy.png

Jerry Stratton
  • 3,287
  • 1
  • 22
  • 30
Frosty
  • 15
  • 8
  • 3
    See http://stackoverflow.com/questions/26041546/ – Alnitak Sep 25 '14 at 14:48
  • 1
    recursion - a function call which (eventually) calls itself again. winding = calling itself again, unwinding = returning from a previous recursive call. – Marc B Sep 25 '14 at 14:49
  • Debug that program in an IDE such as Eclipse, and you can follow the flow in detail. – Magnilex Sep 25 '14 at 14:51
  • 1
    possible duplicate of [Understanding recursion](http://stackoverflow.com/questions/717725/understanding-recursion), which does have some actual content despite the bit of humor at the beginning of the first answer. – Rainbolt Sep 25 '14 at 14:51

6 Answers6

1

When a call is made to another method, a stack frame is created to hold the state of the current method and it is pushed onto the stack. This is regardless of a method calling itself or another method.

When the call returns, the stack frame is popped of the stack, the state of the method is restored and execution continues in the calling method.

Recursion is when a method (directly or indirectly) calls itself. The general form of a recursive method is:

  • If a parameter meets a terminating condition, return (usually a result)
  • Else adjust parameters for the next iteration and call self

The code your teacher wrote has some style issues. It would be clearer if written like this:

static int factorial(int n) {
    if (n == 0) {
        return 1;
    } 
    return n * factorial(n - 1);
}

Eradicating the unnecessary variable t and redundant else (there is no "else" when the "if" returns - there is merely continuation of execution)

I would write it like this, eliminating the if altogether:

static int factorial(int n) {
    return n == 0 ? 1 : n * factorial(n - 1);
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • So if I have multiple conditions, instead of using if, else if{}...else{}, I just use ":" and :?: after each condition until I l am left with no other options ? – Frosty Sep 25 '14 at 15:15
  • @Frosty the ternary operator must be used judiciously: nesting conditions usually loses a lot of readability. – Bohemian Sep 25 '14 at 16:18
1

A recursive function is a function that calls itself until it reaches a return statement, that stops it from recalling itself. Take your example, the Factorial function. Factorial is a mathematical function that returns the number multiplied by itself - 1 multiplied by itself - 2, ... multiplied by 1, example: factorial of 5 = 5! = 5x4x3x2x1 = 120. it is also equal to itself multiplied by the factorial of itself -1, which is: 5! = 5x4! Take into consideration that 0! = 1. to represent this in a Java code, you need a loop that multiplies the numbers starting from 1, and going till the number you are calculating its factorial. Further more, explaining your code, let us calculate Factorial(5): Factorial() returns an integer.

Initial Call from main(): 5 != 0, then skip the condition (n == 0); t = Factorial(5-1) = Factorial(4);

Second call from Factorial(4): 4 != 0, then skip the condition (n == 0); t = Factorial(4-1) = Factorial(3);

Third call from Factorial(3): 3 != 0, then skip the condition (n == 0); t = Factorial(3-1) = Factorial(2);

Fourth call from Factorial(2): 2 != 0, then skip the condition (n == 0); t = Factorial(2-1) = Factorial(1);

Fifth call from Factorial(1): 1 != 0, then skip the condition (n == 0); t = Factorial(1-1) = Factorial(0);

Sixth call from Factorial(0): 0 == 0, then return value 1;

First return, 1, to Fifth call (Factorial(1)): return n*t = return 1*1 = return value 1;

Second return, 1, to Fourth call (Factorial(2)): return n*t = return 2*1 = return value 2;

Third return, 2, to third call (Factorial(3)): return n*t = return 3*2 = return value 6;

Second return, 6, to second call (Factorial(4)): return n*t = return 4*6 = return value 24;

Second return, 24, to First call (Factorial(5)): return n*t = return 5*24 = return value 120;

Second return, 120, to Initial call (from main()): print(120);

Hope this helps you understand recursion.

  • So does every recursive function has a similar logic to this one ? – Frosty Sep 25 '14 at 15:24
  • This is a basic example, that explains the process behind recursion, yes. Recursion is also a major feature when using Binary trees, to search for example, or to insert value based on a logic (knowing where to insert the value, left or right, checking each node... – Hani El Mouallem Sep 25 '14 at 15:29
0

When one knows that a task can be broken into similar smaller tasks ,then we use recursion or calling the same method(until we met a certain condition).Recursion not only helps in execution of a problem without having to define or invoke another method,it also helps in visualizing a pattern by which the task is getting executed

Kumar Abhinav
  • 6,565
  • 2
  • 24
  • 35
  • How do I figure out, in which cases I use a recursive function, and do I construct one ? – Frosty Sep 25 '14 at 15:02
  • If you see that your function can be broken into smaller identical functions ,with decreasing complexity.For example,to find factorial of n,you need (n-1)!*n and (n-1)! can be calculated using (n-2)! and so on.So you will find that defining a single function and calling it with smaller parameters is easier,therefore you should use recursion – Kumar Abhinav Sep 25 '14 at 15:07
0

Personally, I do not like the factorial problem. I find it hard to understand and I do not think it explains recursion in a clear way. So lets look at a different example. Lets say that we want to print numbers from 1-100. This is a very simple task with a for loop and a counter, but it can also be done with recursion. For example:

public static void main(String[] args) {
    numbersAscending(1);
    numbersDescending(1);   
}
//Prints 1 2 3 ... 100
public void numbersAscending(int x){
    System.out.println(x);
    if(x < 100){
        numbersAscending(x+1);
    }
}
//Prints 100 99 98 ... 1
public void numbersDescending(int x){
    if(x < 100){
        numbersDescending(x+1);
    }
    System.out.println(x);
}

When a function is called, that call goes on top of the stack. Think of this like a stack of cards. Each one has a number on it (1-100). When a function calls itself, a new card gets added to the stack. When the function finishes, it is taken off of the stack.

So for the example above, every time numbersAscending is called, it prints out the current value for x before calling that function again. This results in the numbers being printed in order from 1-100. As soon as 100 is reached, it stops calling itself and pops each function off of the stack.

On the other hand, every time numbersDescending is called, it calls itself again before printing out the number. In this way, x doesn't start printing until it reaches 100. It then moves back down the stack, printing each number as it goes back to the main method.

Flyingcows00
  • 223
  • 1
  • 11
0
/*This program in java will help you to understand all the basics of 
  recursion:
  ->how control flows in recursion
  ->how return is executed in the recursive functions
  ->how and when the statements after recursive function area executed.*/

public class Understanding_Rec{

public static int rec(int x)
{
    if(x<5)
    {
        System.out.println("-->Smaller than 5");
        rec(x+1);
        System.out.println("<--After recursion inside x<5");
        return x;
    }
    else if(x<7)
    {
        System.out.println("-->Smaller than 7");
        rec(x+1);
        System.out.println("<--After recursion inside x<7");
    }
    System.out.println("<--No Condition Statement");
    return x;
}

public static void main(String[] args)
{
    int x=1;
    rec(x);
    System.out.print(x+"Inside main");
}
}
Mohanish
  • 19
  • 2
-1

I am not sure if it explains, but if you had a precalculus class then you should know that factorial can be defined in two waqys.

n!=1*2*...*n

of we define

1!=1

and

n!=n*(n-1)!

Try to see yourself that those definitions are equivalent. Pick let us say, 5!

according to second definition

5!=5*4!

but 4!=4*3! so 5!=5*4*3!

but 3!=3*2! so 5!=5*4*3*2!

and so on. Keep doing it until you hit 1!. But 1!=1 so you stop.

Recursion in programming is the same thing.

TomW

tomw
  • 1