Reputation: 249
I'm just new to this Recursion and I know at least that it is a technique by which a method calls itself during execution but I am quite confused on how it actually works.
From the book at school, implementing the factorial function is the first example that was given.
//int n = 5;
private static int factorial(int n) {
if(n == 0) {
return 1;
}
else
return n * factorial(n - 1);
}
I get how this factorial works somehow but I am not completely sure if I understood it correctly. For every call the method refers to itself, n
is multiplied to the factorial parameter n - 1
until it reaches 1
.
This is how I trace this recursion in my mind
5 * factorial(5 - 1) = 20 //first call
20 * factorial(4 - 1) = 60 //second call
60 * factorial(3 - 1) = 120 //third call
120 * factorial(2 - 1) = still 120 // fourth call
120 is the last returned value;
And another example that was given is printing numbers from 1 to n using recursion instead of using the ordinary loop.
//int n = 10;
private static void printNumbers(int n) {
if(n >= 1) {
printNumbers(n - 1);
System.out.print(n + " ");
}
}
This outputs: 1 2 3 4 5 6 7 8 9 10
And now, the thing confuses me here is why the ouput starts at 1
? Because from how I understand it the output should start at 9
up to 1
.
Because from I understood it, at start the n = 10
and then 10 > 1
so of course it will call itself again then 10 - 1
then print 9
and then calls itself again and 9 - 1
then print 8
and so on...
Can anyone please clarify this to me simply and correct my mistaken understanding to the examples I've mentioned, I am a little confused here and most of the post I can see here on StackOverflow about recursion is not really helping (But if there is a real good and clear answer about recursion in here that you know of, do give me the link).
Thank you...
Upvotes: 4
Views: 1102
Reputation: 2987
Take a look at this example which is different than yours but will help you understand how the order of operations affects recursion. It works because of the order of operations on the line of the return.
public int getRSquare(int n){
if(n==0){
return 1;
}
return getRSquare(n-1)*n;
}
You will see with each call of this method, the first thing to occour is the recursive call to getRSquare(n-1). This happens before it multiplies what is returned. The example below calls getSquare(3) then getSquare(2) then getSquare(1) then getSquare(0). It is only after this that the base case n==0 applies and no recursion happens, but a 1 is returned. This returned value is then multiplied with the n of the previous call which is in many cases a different value.
result = getSquare( n=3);
getSquare(n=2)
getSquare(n =1)
getSquare(0)
Return a 1,
return returned value multiplied by n (n is a 1 prev returned value is 1 = 1)
return returned value multiplied by n (n is a 2 prev returned value is 1 = 2)
return returned value multiplied by n (n is a 3 prev returned value is 2 = 6)
You will see the above call to getSquare(3) will return a 6. Remember that n is local to each function call so each activation of the method getSquare will have its own n, as we recurse n gets smaller each time, as we return back up, n gets larger because that's the value it had at the previous method activation.
As a practice task, I recommend is you use this approach so see what happens when you switch the order of operations such as:
public int getRSquare(int n){
if(n==0){
return 1;
}
return n * getRSquare(n-1);
}
Upvotes: 1
Reputation: 996
I'm assuming this question is more about the order of the computations and not so much about understanding the idea of recursion.
With recursion, things occur the other way around to what you have listed. It works like a stack instead of a queue. If you've played card games like MTG, it works just like in the games. Last thing "activated" is done first.
Basically, the first time you call the factorial function, it stalls at this point:
return n * factorial(n - 1);
Because your program is now waiting for the result of factorial(n - 1) to proceed.
It will keep calling subroutines (which, if big enough, can cause a stack overflow exception, what this site is named after).
Eventually, n will be equal to 0, and this branch will execute:
return 1;
So, at the top of your stack, you will have factorial(1) waiting for the result of factorial (0).
return 1 * factorial(0); //come on hurry up factorial(0)!
Now with 0 being taken care of, 1 is ready to return it's value.
return 1 * 1; //1 replaces factorial(0), now we can return!
Now we're at N = 2, still stuck at the same place.
return 2 * factorial(1); //need factorial(1) to continue!
After factorial(1) returns we get:
return 2 * 1; //ready to return!
Then at N=3 (or factorial(3))
return 3 * 2; //2 replaces factorial(2), now ready to return.
...and so on until
return n * factorial(n - 1); //been waiting forever...
Now the other example:
//int n = 10;
private static void printNumbers(int n) {
if(n >= 1) {
printNumbers(n - 1);
System.out.print(n + " ");
}
}
The program will halt at printNumbers(n - 1); in this case. It won't suddenly forget about the original call printNumbers(n), but it needs to do printNumbers(n - 1) first.
So starting with N = 10, it will say "okay to continue, I have to figure out what printNumbers(9) is. And then at N = 9, the same occurs with printNumbers(8).
At N = 1, we have printNumbers(0), which does nothing. So N = 1 proceeds to the next line and prints. Then returns back to the halted method N = 2, which was still waiting for printNumbers(1) to finish. N = 2 prints and returns void, allowing N = 3 to continue and so on until N = 10.
Upvotes: 1
Reputation: 3097
Because in fact nothing happens until the last call to factorial()
returns 1
. Internally, all intermediate results are "piled up" on the stack and then "piled down" when the function returns.
So in fact, a call to factorial(3)
does
factorial(3) = 3 * factorial(2) -->> 3 on the heap
factorial(2) = 2 * factorial(1) -->> 2,3 on the heap
factorial(1) = 1 * factorial(0) -->> 1,2,3 on the heap
factorial(0) = 1
Once the factorial(0)
finally returns, all multiplications are rolled up:
1 * 1 * 2 * 3 = 6
Or written the other way:
factorial(0) = 1
factorial(1) = 1 * (1)
factorial(2) = 2 * (1 * (1))
factorial(3) = 3 * (2 * (1 * (1)))
factorial(4) = 4 * (3 * (2 * (1 * (1))))
...
Each opening parenthesis is a function call that pushes a value on the stack, and the multiplications can occur only when both left and right values are known, which is when it reaches 0
and returns 1
.
Upvotes: 1
Reputation: 83
Recursion is by no means an easy concept -- most people have trouble with it so you're not alone.
Thinking about a problem recursively means that some computation gets repeated until the problem is solved (i.e. the base case is reached or the method is exhausted. For the Factorial, it is when n=0, for the number print, the method is exhausted [does nothing]). When this happens, the most recent computation is returned up the recursion level until there are no more levels left. Thus, the problem is solved.
Here's an analogy: Think of this process as if you were mining. The computation (or procedure) for mining (roughly) is to dig until you find what you want (let's say gems). You start at the surface of the Earth. Are there gems? This question is your base case-you will stop mining when you find your gems. If there aren't gems, you must dig deeper (go down a level), so you call up the mining procedure. You ask yourself again, are there gems? If there aren't gems, you must dig deeper, etc. This will repeat, or recurse, until you can answer the question with 'Yes! I have found gems.' Once the base case is reached, you are at the lowest level in the process, right? When mining, once you find the gems, you can't stay at the bottom of the mine. You must return to the top with the gems you have.
That's recursion in a nutshell. Now to address your understanding:
You're correct with the conditional, 10 >= 1, so call printNumbers(10 - 1), and so on. However, it prints with 1 because that was the first thing returned. If you look at the code, you'll notice that printNumbers(10 - 1) is called before System.out.println(n + " ");. That means that before 10 is printed, printNumbers runs 9. When we get to printNumbers(1), this is what happens:
That's all there is to it really. If there's any confusion, let me know!
Upvotes: 2