I read about recursion in Programming Interviews Exposed (3rd ed.) where they present the following recursive factorial function:
int factorial(int n){
if (n > 1) { /* Recursive case */
return factorial(n-1) * n;
} else { /* Base case */
return 1;
}
}
On the bottom of the same page (page 108) they talk about tail-recursive functions:
Note that when the value returned by the recursive call is itself immediately returned, as in the preceding definition for factorial, the function is tail-recursive.
But is this really the case here? The last call in the function is the * call, so won't this stack frame be preserved (if we don't take compiler optimization into account)? Is this really tail-recursive?
You can rewrite it to be tail-recursive:
int factorial(int n){
return factorial2(n, 1);
}
int factorial2(int n, int accum) {
if (n < 1) {
return accum;
} else {
return factorial2(n - 1, accum * n);
}
}
No, it's not tail-recursive. The result being returned by factorial(n-1) still has to be multiplied by n, which requires that factorial(n) regain control (thus mandating that the call to factorial(n-1) be a call rather than a jump).
With that said, even if it were tail-recursive, the compiler still might not do TCO on it. Depends on the compiler and the optimizations that you ask it to do.
Quoting from this link: tail recursion using factorial as example
factorial(n) {
if (n == 0) return 1;
return n * factorial(n - 1);
}//equivalent to your code
This definition is NOT tail-recursive since the recursive call to
factorial is not the last thing in the function
(its result has to be multiplied by n)
Tail Recursive is a special case of recursion in which the last operation of the function is a recursive call. In a tail recursive function, there are no pending operations to be performed on return from a recursive call.
The function you mentioned is not a tail recursive because there is a pending operation i.e multiplication to be performed on the return from a recursive call.
In case you did this:
int factorial(int n,int result)
{
if (n > 1)
{ /* Recursive case */
return factorial(n-1,n*result);
}
else
{ /* Base case */
return result;
}
}
would be a tail recursive function. since it has no pending operation on return from a recursive call.
Related
If I put a break point on this function it will step through until the base case is met but when it hits the return 1 it doesn't actually exit the loop. Instead it goes to the bottom bracket and then bounces to int t = expo(m, n / 2) and steps downs to return t * t*m. It then goes back to the bottom bracket and repeats this process before eventually stopping. Can someone explain what is going on?
int expo(const int m, const unsigned int n) {
funcCallCounter++; //counts how many times the function is called
if (n == 0) {
return 1;
}
else {
if (n % 2 == 0) {
int t = expo(m, n / 2);
return t * t;
}
else {
int t = expo(m, n / 2);
return t * t*m;
}
}
}
When the flow of your program in a function encounters a return statement, control is returned to place that called that function. That is true even if it was the same function. This is completely normal and expected.
In your case, each call still has work to do after the recursive step (because your expo() call is never quite the last thing before return) and you're seeing the program get on with that work.
Keep an eye on your stack frame while debugging; you'll see that it's not really jumping around in the way that you think it is; you're returning to previous call contexts.
I just started to learn about recursion.
This program is supposed to calculate n! and store the result into an output parameter.
void factorial(int n, int &f)
{
if (n == 0)
{
f = 1;
}
else
{
factorial(n - 1, f);
f *= n;
}
}
int main()
{
int f;
factorial(5, f);
cout << f;
}
This way it works perfectly. In my first attempt, the else condition looked like this
else
{
f *= n;
factorial(n - 1, f);
}
and the program didn't output anything but 1.
I really can't understand why it works in the first way but in the second it doesn't. Can you explain to me?
In your code, factorial(0, f) will set f = 1. If you modify f before the call to factorial, it will be overwritten.
Note that this problem is not possible if you return int instead of taking int & as an argument.
For anyone wondering:
Using #ForceBru's suggestion I ran it on a piece of paper and I got it. If I do it in the second way, the last thing called will be factorial(0) which will return 1, even if I already calculated to be n!.
f is getting over written to 1 in your last call f(0). If you switch the statements then f gets initialized to 1 in the last call f(0) followed by It's modification before return of each function call
I thought up to this point in time, that I understood how a return works, but once I got into the recursions, I suppose I'm a bit more lost than the originally thought.
Suppose, I have a function for count, that how many times a char pops up in a string.
int frequency(char ch, string input, int pos) {
if (pos == inputString.length()) {
return 0;
}
if (inputString[pos] == ch) {
return 1 + frequency(ch, inputString, pos + 1);
}
else {
return frequency(ch, inputString, pos+1);
}
}
If I were to pass to it, the string "Jeff" and looking for "f", it returns a value of 2.
So, how does it know when to stop?
Does return 0 end any method with return type int?
And if so, why does it still return the value of 2, when the final return says return 0?
The last return
return 0;
is only the last time the function is called during the recursion. This is needed to stop the recursion at some point. For the call before this last one one of the other return statements is executed, e.g:
return 1 + frequency(ch, inputString, pos + 1);
Thus the 0 is added up to the 1 and any previous results of the recursion.
PS:
As long as the function return statement calls the function again the recursion continues. Only when the return simply returns something (without calling the fucntion again) the recursion stops.
Here is a more simple example that calculates the sum of all integers up to N:
int calcSum(int N){
if ( N == 1 ) return 1; // recursion stops here
return N + calcSum( N-1 ); // otherwise continue to add up
}
Multiple return statements in one function are not special to recursion. The function just returns on the first return it encounters.
So, how does it know when to stop?
When no more recursive calls are added from a particular branch in the recursively called function it will stop, and the call stack will be cleared with returning values in the reverse order of the calls were issued (LIFO). That's done here:
if (pos == inputString.length()) {
return 0;
}
Any of the other branches call the function recursively and take a step down in the call stack:
if (inputString[pos] == ch) {
return 1 + frequency(ch, inputString, pos + 1);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
else {
return frequency(ch, inputString, pos+1);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
Does return 0; end any method with return type int?
Yes, and it will do for any return types that can be initialized with 0
And if so, why does it still return the value of 2, when the final return says return 0?
Because the results of the recursive call results were accumulated on the stack:
return 1 + frequency(ch, inputString, pos + 1);
// ^ the result of the operation will be saved on the stack when the call returns
... and you see the final result of the (first) recursive call in your driver function.
BTW, the much cheaper implementation by means of performance and memory usage would be a simple loop. There aren't any drawbacks regarding the linear time behavior anyway:
int frequency(char ch, string input) {
int result = 0;
for(int pos = 0; pos < input.size(); ++pos) {
if (input[pos] == ch) {
++result;
}
}
return result;
}
Think of a recursive calls as a stack of function calls. At some point it may hit return 0; This mean that one of the function calls on the stack is completed. Thus an element on the stack is popped. The function's final return happens when the stack is empty.
I understand tail-recursion however I have been assigned to write a code to see what the N'th Fibonacci number is.
To begin, this code does work. It's not the best way but it's one way--however I'm starting to worry that it isn't tail recursive. The code is here:
static int fib_tail_helper(int n, int result) {
if (n == 0) {
return result;
}
else if (result == 0) {
return fib_tail_helper(n - 1, result + 1);
}
else {
return fib_tail_helper(n - 1, result + fib_tail_helper(n - 1, 0));
}
}
int fib_tail(int n) {
/*
// REQUIRES: n >= 0
// EFFECTS: computes the Nth Fibonacci number
// fib(0) = 0
// fib(1) = 1
// fib(n) = fib(n-1) + fib(n-2) for (n>1).
// MUST be tail recursive
*/
return fib_tail_helper(n, 0);
}
I'm mostly worried about the "return fib_tail_helper(n - 1, result + fib_tail_helper(n - 1), 0".
I feel as if that would use another stack, and thus be non-tail-recursive... Can anyone give some input?
Thanks!!
No it is not tail-recursive.
The compiler needs to evaluate the fib_tail_helper argument first, which means it will create n-1 call stacks before it proceeds to call the last fib_tail_helper as the return value.
To show that it's not tail-recursive a transformation might help:
static int fib_tail_helper(int n, int result) {
if (n == 0) {
return result;
}
else if (result == 0) {
return fib_tail_helper(n - 1, result + 1);
}
else {
int tailrecursivePreventingValue = fib_tail_helper(n - 1, 0);
return fib_tail_helper(n - 1, result + tailrecursivePreventingValue);
}
}
It does exactly the same as your code but introduces an explanatory variable. You can see that there are 2 calls to fib_tail_helper() in the last else-block. This means exponential running time since the second value depends on the first one.
Tail recursion is a clever implementation of recursion, that does not use stack space.
It works like this:
If a function calls itself, as it's last action, then that is called "tail recursion".
In this special case, a compiler can forgo doing an actual function call. It can execute a goto back to the beginning of the function. The code of the function will run again, just as if it had been called. When the function terminates, it will return to the last address on the stack, which is the function that originally called the recursive function.
This approach guarantees that the stack does not overflow, no matter how deep the recursion goes. That is what is so great about tail recursion.
The bad news is that C++ does NOT automatically support tail recursion.
The good news is that it is trivially easy to implement tail recursion.
You simply replace the final function call with a goto back to the beginning of the function.
(This is just you writing the goto that the compiler would, if it supported tail recursion.)
I'm trying to answer this question from my C++ book that says: There are n people in a room, where n is an integer greater than or equal to 2. Each person shakes hands once with every other person. What is the total number of handshakes in the room? Write a recursive function to solve this problem.
I've written a program, but nothing is being outputted from the function. I'm pretty sure my stuff inside the handshake function is correct, but nothing is being outputted by the function inside the main function. It keeps giving me an error:
Unhandled exception at 0x00c01639 in Problem2.exe: 0xC00000FD: Stack overflow.
Thank you for your help in advance!
#include <iostream>
#include <conio.h>
using namespace std;
int handshake(int n);
int main()
{
int i, n;
cout<<"How many people are in the room? ";
cin>>i;
for (n = 1; n = i; n++)
{
handshake(n);
}
cout<<"There are "<<handshake(n)<<" in the room"<<endl;
getche();
return 0;
}
int handshake(int n)
{
if (n == 1)
{
return 0;
}
else if (n == 2)
{
return 1;
}
else
{
return (handshake(n) + (n - 1));
}
}
Your problem is here:
return (handshake(n) + (n - 1));
Notice you're returning handshake(n) on a call of handshake(n), throwing you into infinite recursion land (and causing the call stack to overflow, hence your error).
This sounds like homework so I won't give any specific solution. I will make the following remarks:
Recursive functions need to have a base case (which you have) and a recursive step (which you need to fix). In particular, if f(x) is a recursive function, its result should depend on f(x-e), where e is strictly greater than 0.
You only need to call a recursive function once in your main code; it will take care of calling itself when needed.
The problem is because of stackoverflow which happens because the call to handshake(n) is making a recursive call to handshake(n) again and this infinite recursive calls causes the stack to explode.
Recursive calls should be called with arguments that are closer to the values that lead to base conditions, 0 and 1 in your case.
In your case the correct recursive call is:
return (handshake(n-1) + (n - 1));
As the recursive formula for number of hand shakes in a party is:
H(n) = H(n-1) + n-1
with the base condition of H(1) = 0 and H(2) = 1 where n is the number of people in the party and H(n) is the number of handshakes when every person in the party shakes hand with every other person in the party.
Also the condition in your for loop:
for (n = 1; n = i; n++)
will assign i to n. But what you want is to compare the value as:
for (n = 1; n <= i; n++)