Recursive function to loop and stack - loops

It's well known all recursive functions can be written using just a single loop and a stack. Although this conversion can be criticized to be ugly or less readable, its main use is obviously to avoid smashing the heap.
There are natural ways to convert simple recursive functions into loops. For instance, take the simple tail-recursion elimination using an accumulator. So far, I have not seen yet a definitive answer for this question.
At least to me, sometimes it seems black magic to convert such recursive functions into loops provided a stack. For instance, think of writing a non-recursive version for
f(n) = n, if n <= 1
f(n) = f(n-1) + f(n-2) + 1, if n > 1
The very point underlying this question is:
Is there a lucid, general method to convert a recursive function into a loop + stack?

Feasibility (100%):
From here, we know that any recursive function can be converted to iterate (into a loop) but you need to use a stack yourself to keep the state.
How to do this (generally):
You can check out the article How to replace recursive functions using stack and while-loop to avoid the stack-overflow, which gives examples and steps (10 steps/rules) on how to convert recursive functions to stack and while-loop. See the following part for real example.
Example:
Take the following recursive function as an example:
// Recursive Function "First rule" example
int SomeFunc(int n, int &retIdx)
{
...
if(n>0)
{
int test = SomeFunc(n-1, retIdx);
test--;
...
return test;
}
...
return 0;
}
After applying the 10 rules/steps introduced in the article (details shown in comments), you will get:
// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
// (First rule)
struct SnapShotStruct {
int n; // - parameter input
int test; // - local variable that will be used
// after returning from the function call
// - retIdx can be ignored since it is a reference.
int stage; // - Since there is process needed to be done
// after recursive call. (Sixth rule)
};
// (Second rule)
int retVal = 0; // initialize with default returning value
// (Third rule)
stack<SnapShotStruct> snapshotStack;
// (Fourth rule)
SnapShotStruct currentSnapshot;
currentSnapshot.n= n; // set the value as parameter value
currentSnapshot.test=0; // set the value as default value
currentSnapshot.stage=0; // set the value as initial stage
snapshotStack.push(currentSnapshot);
// (Fifth rule)
while(!snapshotStack.empty())
{
currentSnapshot=snapshotStack.top();
snapshotStack.pop();
// (Sixth rule)
switch( currentSnapshot.stage)
{
case 0:
// (Seventh rule)
if( currentSnapshot.n>0 )
{
// (Tenth rule)
currentSnapshot.stage = 1; // - current snapshot need to process after
// returning from the recursive call
snapshotStack.push(currentSnapshot); // - this MUST pushed into stack before
// new snapshot!
// Create a new snapshot for calling itself
SnapShotStruct newSnapshot;
newSnapshot.n= currentSnapshot.n-1; // - give parameter as parameter given
// when calling itself
// ( SomeFunc(n-1, retIdx) )
newSnapshot.test=0; // - set the value as initial value
newSnapshot.stage=0; // - since it will start from the
// beginning of the function,
// give the initial stage
snapshotStack.push(newSnapshot);
continue;
}
...
// (Eighth rule)
retVal = 0 ;
// (Ninth rule)
continue;
break;
case 1:
// (Seventh rule)
currentSnapshot.test = retVal;
currentSnapshot.test--;
...
// (Eighth rule)
retVal = currentSnapshot.test;
// (Ninth rule)
continue;
break;
}
}
// (Second rule)
return retVal;
}
BTW, the above article is the Prize winner in Competition <Best C++ article of July 2012> of CodeProject, so it should be trust-able. :)

Yes, but the solution won't be much better than the recursive one except maybe reduce the chance for a stack overflow.
By looking at the sequence, which is similar to the Fibonacci sequence except you add 1 to the result for every round except n = (0,1), you see a pattern.
0 1 2 4 7 12 20
\ \___ ...\____
0+1+1 1+2+1 7+12+1
Since the whole generation is dependent on the two previous numbers you can have two variables in a loop representing that and you don't need to have a stack at all.
//intentional generic algol dialect
int modfib (int n)
{
if( n <= 1 )
return n;
n = n - 2;
int a=2;
int b=4;
int tmp;
while( n-- > 0 )
{
tmp=a;
a=b;
b = tmp + b +1;
}
return a;
}
Until compilers know to do this we still need humans to optimize code.

Related

Where do recursive functions end?

#include <stdio.h>
int factorial(int n);
void main()
{
int n;
printf("Enter your number : " );
scanf("%d",&n);
if(n <= 1)
{
printf("The factorial of the number n is ",n);
}
else
{
int res = factorial(n);
printf("The result is %d\n",res);
}
}
int factorial(int n)
{
if(n <= 1)
return 1;
return n * factorial(n-1);
}
I'm doing a recursive function concept for the first time and i pretty much got like a 65% grasp on the concept of recursion. In the above program i have written a factorial recursion function and it goes normally well and i get the output but i'm trying to think where the recursion ends
Like for example i have gave an input of 5 :
The result is 120
but the main thing i wanted is why it doesn't continue after 0, if n <= 1(given if n = 0,-1...and so on during recursion) and then it should keep on returning "1" and multiplying with the recursion function(the factorial function being called inside the "factorial" function).In conclusion I really have no idea where the recursion ends...can you please clear it up.
Lets say you have call factorial(3), then the call-chain will be something like this:
factorial(3) // Initial call
factorial(2);
factorial(1);
return 1; // No more recursion
return 2 * 1; // 1 is the result of factorial(1)
return 3 * 2; // 2 is the result of factorial(2)
The result of factorial(3) will be 6 (3 * (2 * 1)).
In conclusion I really have no idea where the recursion ends..
It ends at the return 1; statement:
int factorial(int n)
{
if(n <= 1)
return 1; <---- Here
return n * factorial(n-1);
}
Maybe it's more clear if you wrote it like:
int factorial(int n)
{
if(n <= 1)
{
// No more recursive calls - just return 1
return 1;
}
else
{
// Do recursive call with decremented argument
return n * factorial(n-1);
}
}
So the code keeps doing recursive calls until n becomes 1. Then it returns 1 to the previous recursive call which returns 2 (2 * 1) to the previous recursive call which returns 6 (3 * 2) to the previous recursive call which returns 24 (4 * 6) .... and so on.
So the final result is calculated like:
1 * 2 * 3 * 4 * ...
\---/
2 * 3
\-------/
6 * 4
\-----------/
24
From Recursion:
In mathematics and computer science, a class of objects or methods exhibits recursive behavior when it can be defined by two properties:
A simple base case (or cases) — a terminating scenario that does not use recursion to produce an answer.
A recursive step — a set of rules that reduces all successive cases toward the base case.
So, terminating scenario('s)/condition('s) is one of property of recursion and it's where the recursion ends.
In context of your program:
Your program is finding the factorial of a given number n.
The factorial of a non-negative integer n is the product of all positive integers less than or equal to n:
n ! = n * ( n − 1 ) * ( n − 2 ) * ( n − 3 ) * ..... * 3 * 2 * 1
which is equivalent to
n ! = n * ( n - 1 ) !
that means, when writing program to calculate the factorial of a number n, we have to calculate the product of all positive integers and stop when reached to 1, which is the terminating condition.
In factorial() function:
int factorial(int n)
{
if(n <= 1)
return 1;
return n * factorial(n-1);
}
The condition if(n <= 1) is the terminating condition for recursive function finding the factorial of n and its where the recursive function factorial() ends.
Additional:
In your program, you are missing the format specifier in this
printf() statement:
printf("The factorial of the number n is ",n);
it should be
printf("The factorial of the number n is %d\n",n);
^^
Note that, 0! is 1 and, after making above change, your program
will give output as 0 when user give input number 0 which is
wrong.
May you should write function to calculate factorial of given positive number n like this:
unsigned int factorial(unsigned int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
and add a check on user input before calling factorial(). This will take care of 0! as well.
Using void as return type of main function is not as per
standards. The return type of main function should be int.
To understand simple recursive code, it helps a lot to draw a diagram (recursive trace). I will draw it in paint, but it's even better to do it on paper. Let's say we are calling factorial(3).
Write down the call of the function. (In the beginning, it's factorial(3))
Ask yourself: "Is the exit condition satisfied?" (In your case the condition is if(n <= 1))
If the answer is yes, check what gets returned and write it under the previous function call, then go to the next step. You have return 1; so 1 gets returned.
If the answer is no, check what gets returned and write it under the previous function call. You have return n*factorial(n-1); so the first time the return value will be 3*factorial(3-1), which is equal to 3*factorial(2). Now go back to step 1) with the new function call and repeat the process until the condition is satisfied. The call here is factorial(2). You can also connect the function calls with arrows to make the diagram more organized.
This is how the diagram should look like when your condition is satisfied:
You now go from the bottom upwards:Write down the value of the very bottom function call, and repeat for every function call above that. In your case, you first write the value of factorial(1), which is 1, then you move up, and you see that factorial(2) is equal to 2*factorial(1). And because you know that factorial(1) is equal to 1, you also know that
factorial(2) is equal to 2.
You can connect the function calls upwards to make the diagram more organized.
You are done. The diagram should look something like this:
With this diagram, we know exactly when the recursion stops - when factorial(1) is called. We also know the end result, which is 6.

Is it cheating to use 'static' when writing a recursive algorithm?

As part of a programming assignment, I'm required to write a recursive function which determines the largest integer in an array. To quote the exact task:
Write a recursive function that finds the largest number in a given list of
integers.
I have come up with two solutions, the first of which makes two recursive calls:
int largest(int arr[], int length){
if(length == 0)
return 0;
else if(arr[length - 1] > largest(arr,length -1))
return arr[length];
else return largest(arr,length -1);
}
The second one makes only one, however it uses a static variable n:
int largest(int arr[], int length){
static int n = -1;
if(length == 0)
return n;
else if (arr[length - 1] > n)
n = arr[length - 1];
return largest(arr, length - 1);
}
I was wondering whether it would be considered cheating use static variables for such a task. Either way, which one is considered better form? Is there a recursive method which tops both?
I wouldn't say that it's cheating to use static variables this way - I'd say that it's incorrect. :-)
Imagine that you call this function multiple times on a number of different arrays. With the static variable introduced, the value of n never resets between calls, so you may end up returning the wrong value. Generally speaking, it's usually poor coding style to set things up like this, since it makes it really easy to get the wrong answer. Additionally, if your array contains only negative values, you may return -1 as the answer even though -1 is actually bigger than everything in the array.
I do think that the second version has one nice advantage over the first - it's much, much faster because it makes only one recursive call rather than two. Consider using the first version, but updating it so that you cache the value returned by the recursive call so that you don't make two calls. This will exponentially speed up the code; the initial version takes time Θ(2n), while the updated version would take time Θ(n).
There is nothing cheating using a static inside function, recursive or otherwise.
There can be many good reasons for why to do so, but in your case I suspect that you are coming up with a wrong solution -- in as largest will only work once in the lifetime of the program running it.
consider the following (pseudo) code;
main() {
largest([ 9, 8, 7]) // would return 9 -- OK
largest([ 1, 2, 3]) // would return 9 ?? bad
}
The reason being that your largest cannot tell the difference between the two calls, but if that is what you want then that is fine.
Edit:
In answer to your comment, something like this will have a better big-O notation than your initial code;
int largest(int arr[], int length){
int split, lower,upper;
switch (length) {
case 1: return arr[0];
case 2: if (arr[1]>arr[0]) return arr[1]; else return arr[0];
default:
if (len <= 0) throw error;
split = length/2;
lower = largest(arr,split);
upper = largest(arr+split,length-split);
if (lower > upper) return lower; else return upper;
}
}
Alternatively, the obvious solution is;
int largest(int arr[], int length){
if (length <= 0) thor error;
int max = arr[0];
for (int i=1; i<length; i++)
if (arr[i] > max) max = arr[i];
return max;
}
which has no recursion at all
It is actually a terrible design, because on the second execution of the function does not return a correct result.
I don't think you need to debate whether it is cheating, if it is wrong.
The first version is also incorrect, because you return arr[length] instead of arr[length-1]. You can eliminate the second recursive call. What can you do instead of calling the same function (with no side-effects) twice with the same arguments?
In addition to the excellent points in the three prior answers, you should practice having more of a recursion-based mind. (1) Handle the trivial case. (2) For a non-trivial case, make a trivial reduction in the task and recur on the (smaller) remaining problem.
I propose that your proper base case is a list of one item: return that item. An empty list has no largest element.
For the recursion case, check the first element against the max of the rest of the list; return the larger. In near-code form, this looks like the below. It makes only one recursive call, and has only one explicit local variable -- and that is to serve as an alias for the recursion result.
int largest(int arr[], int length){
if(length == 1)
// if only one element, return it
return arr[0];
else n = largest(arr,length-1))
// return the larger of the first element or the remaining largest.
return arr[length-1] > n ? arr[length-1] : n
}
Is there a recursive method which tops both?
Recursion gets a bad name when with N elements cause a recursion depth of N like with return largest(arr,length -1);
To avoid this, insure the length on each recursion is halved.
The maximum recursive depth is O(log2(N))
int largest(int arr[], int length) {
if (length <= 0) return INT_MIN;
int big = arr[0];
while (length > 1) {
int length_r = length / 2;
int length_l = length - length_r;
int big_r = largest(&arr[length_l], length_r);
if (big_r > big) big = big_r;
length = length_l;
}
return big;
}
A sneaky and fast method that barely uses recursion as finding the max is trivial with a loop.
int largest(int arr[], int length) {
if (length <= 0) return INT_MIN;
int max = largest(NULL, -1);
while (length) {
length--;
if (arr[length] > max) max = arr[length];
}
return max;
}

Tail recursion call (C primer plus book example)

In the C Primer Plus (6th edition), it defines the tail recursion concept
in this manner:
In the simplest form of recursion, the recursive call is at the end of the function, just before the return statement. This is called tail recursion, or end recursion, because the recursive call comes at the end. Tail recursion is the simplest form because it acts like a loop.
And it gives an example of calculating the factorial in a tail recursive manner:
long rfact(int n) {
long ans;
if (n > 0)
ans = n * rfact(n - 1);
else
ans = 1;
return ans;
}
It also makes a side note, which is not true in my opinion:
Note that although the recursive call to rfact() is not the last line in the function, it is the last statement executed when n > 0, so it is tail recursion.
One can clearly see that the last statement is n * rfact(n - 1) which, if you recursively expand, it will lead to a chain of deferred multiplications. The process is recursive in nature, so the implementation cannot be tail recursive as described here.
The example is misleading. What is your opinion?
As far a good C programming book goes, I used the C programming language.
You are correct in saying this is not tail recursion. The typical tail recursion example for a factorial is:
int factorial(int x) {
return tailfactorial(x, 1);
}
int tailfactorial(int x, int multiplier) {
if (x <= 0) {
return multiplier;
}
return tailfactorial(x - 1, x * multiplier);
}
I imagine that your book did not explain the purpose for tail recursion. Tail recursion is used in order to not increase the "stack depth". The compiler can replace the recursive call with a "goto" command which does not increase the stack depth. This compiler modification is only made when the value of the recursion is returned directly. You will notice in your example that this is not the case.
The given definition and example both are misleading. The definition of tail recursion is:
A function call is said to be tail recursive if there is nothing to do after the function returns except return its value.
It is not not necessary that recursive call should be just before the return statement or last statement of the function. See an example:
function foo(data) {
a(data);
return b(data);
}
In this case a is just before the return statement but b is in tail position.
function bar(data) {
if ( a(data) ) {
return b(data);
}
return c(data);
}
In this example, both b and c are in tail position though b is not at the end of the function bar.
In your given example, the last thing function is performing before return is multiplication
ans = n * rfact(n - 1);
Therefore, its not a tail recursive function.
Am example of tail recursive function is
factorial1(n, accumulator) {
if (n == 0) return accumulator;
return factorial1(n - 1, n * accumulator); // The last thing, before return, performed
// by factorial1 is to call itself.
}
factorial(n) {
return factorial1(n, 1);
}
which may be optimize by compiler to
factorial1(n, accumulator) {
while (n != 0) {
accumulator *= n;
n -= 1;
}
return accumulator;
}

Pointers in C with recursion

I usually program in java and recently watching some c codes.
I came up across this program and I don't know how this pointer thing is working.
I know pointer stores the address and all but couldn't make it through the program.
Please tell how is the output coming as 8 ?
#include <stdio.h>
int fun(int n, int * f_p) {
int t, f;
if (n <= 1) {
*f_p = 1;
return 1;
}
t = fun(n - 1, f_p);
f = t + *f_p;
*f_p = t;
return f;
}
int main() {
int x = 15;
printf("%d\n", fun(5, &x));
return 0;
}
What you have here is a recursive function that calculates the i-th element of a Fibonacci sequence (indexing from 0). Each recursive iteration returns two values: the i-th Fibonacci number and the (i-1)-th (previous) Fibonacci number. Since a function in C can only return one value (well, unless you use a struct as return type), the other value - the previous Fibonacci number - is returned to the caller through a pointer parameter f_p.
So, when you call fun(5, &x), the function will return 8, which is the 5-th Fibonacci number, and it will also place 5 into x, which is the previous (4-th) Fibonacci number.
Note that the initial value of x does not matter. That 15 does not play any role in this program. Apparently it is there as a red herring.
If you know what a Fibonacci sequence is, you know that the next element of the sequence is the sum of the two previous elements. This is why the function is written to "return" two elements of the sequence to the caller. You might not care about that previous value in the top-level caller (i.e in main), but the nested recursive calls do need it to calculate the next number. The rest is pretty straightforward.
Step by step:
fun gets called with a 5 and the x address
fun calls fun with a 4 and f_p, which is the x address
fun calls fun with a 3 and f_p, which is the x address
fun calls fun with a 2 and f_p, which is the x address
fun calls fun with a 1 and f_p, which is the x address
fun got called with a 1 so the if condition is true, puts a 1 in the variable pointed by f_p(x) and returns 1
this returned value is assigned to the t of the fun(2,f_p), f is f = t + *f_p which is 1+1 -> f=2;
the variable pointed by f_p is set to t so x=1, returns f so it returns 2
this returned value is assigned to the t of the fun(3,f_p), f is f = t + *f_p which is 2+1 -> f=3;
the variable pointed by f_p is set to t so x=2, returns f so it returns 3
this returned value is assigned to the t of the fun(4,f_p), f is f = t + *f_p which is 3+2 -> f=5;
the variable pointed by f_p is set to t so x=3, returns f so it returns 5
this returned value is assigned to the t of the fun(5,f_p)(the first call to fun), f is f = t + *f_p which is 5+3 -> f=8;
the variable pointed by f_p is set to t so x=5, returns f so it returns 8, which is what the printf prints
Another answer revealed this to calculate the fibonacci numbers using a useful technique for returning an extra value. I've rewritten the code in what I think is a much more understandable and maintainable manner. Hope this prevents people thinking you need to write terrible code to do something like this
#include <stdio.h>
int fib(int n) {
// This is used to return the previous fib value
// i.e. fib(n - 1)
int prevValRet;
return fibRec(n, &prevValRet);
}
// *prevValRet contains fib(n-2)
int fibRec(int n, int *prevValRet) {
// Termination case
if (n <= 1) {
// return fib(0) and fib(1) as 1
*prevValRet = 1;
return 1;
}
// Calculate fib(n-1)
int prevVal = fibRec(n - 1, prevValRet);
// Calculate fib(n) = fib(n-1) + fib(n-2)
int thisVal = prevVal + *prevValRet;
// Return fib(n-1) and fib(n)
*prevValRet = prevVal;
return thisVal;
}
int main() {
printf("%d\n", fib(5));
return 0;
}
As these things go, it's technically straightforward, but...stupid, in the sense that nobody should do things like this. It's a bad use of recursion and badly-written recursion, given the side effects.
The original call of fun(5, &x) isn't going to trip the condition. So, it'll recurse four times (5-1, 4-1, 3-1, 2-1). That's your base condition, which has the effect of setting the pointed-to location (the original x) to 1 and returning 1.
Then we unroll the four calls, each time adding the returned value to the thing at the pointer and changing the thing at the pointer to be that sum.
In simple English, you're doubling one three times.
Edit: As pointed out, I misread the code as assigning f to *f_p rather than t. That makes it a Fibonacci counter.

Can Recursion be named as a simple function call?

Please consider an Recursive function :
1) int calc(int num)
{
2) sum=sum+num;//sum is a global variable
3) num--;
4) if(num==0)
5) return sum;
6) calc(num);
}
It calculates the sum of an integer .
My teacher told me it's not recursion, but a simple function call, because you need to pass
num-- as an argument and return calc(num--) .
I was shocked, as I knew only one thing when a function call itself, its recursion.
She also gave the reason, that line no. 2 and 3 is stored extra in stack memory.
I have no idea what she was referring to.So after going through stack storage thingy:
Here, I noticed that the function arguments passed are in a recursive way, like n-- in my function.
So that they can be linked to the next function call.
For just this sake, can we term it a simple function call instead of recursion?
The teacher has something quite specific in mind even though what you presented is, technically, recursive. Another form which wouldn't depend upon the global would look something like this:
int calc(int num) // Assume this is valid for non-negative numbers
// In that case, type "unsigned int" would be more appropriate
{
if ( num < 0 )
return -1; // Consider this an error; won't happen in recursive case
if ( num == 0 )
return 0;
return num + calc(num-1);
}
You are correct, recursion is a function that calls itself. PERIOD. There are other points worth separately discussing about global variables, and other good programming practices, but whether you implement the decrement operator in the line of code where you call the function recursively or prior to that point, you are still making a recursive call.
It looks like you're trying to calculate, for a given num, the sum of 0 to num. The calc function really just needs one argument, num, and can then call a helper function calc_num which takes the current number and the running sum:
int calc( int num ) {
return calc_help( num, 0 );
}
Then, calc_help, given a current number, and the sum so far, checks whether num is less than or equal to zero. If it is, then the current running sum is the final sum and can be returned. Otherwise, a recursive call to calc_help is made. The current number for it will be one less than num (so that we're calling calc_help with successively smaller first arguments, getting closer and closer to the case where num <= 0), and the current sum will be sum plus the current number:
int calc_help ( int num, int sum ) {
return num <= 0 ? sum : calc_help( num-1, sum+num );
}
In a language (like Scheme) that performs tail call optimization, this is essentially the following loop. Some C/C++ compilers do perform tail call optimization (e.g., according to Tail recursion in gcc/g++, GCC will optimize tail calls when -O2 is specified), so this isn't entirely a moot point.
int calc( int num ) {
int sum = 0;
while ( num > 0 ) {
sum = sum+num;
num = num-1;
}
return sum;
}
or (if you want to be a bit more obscure):
int calc( int num ) {
int sum = 0;
for ( ; num <= 0; sum+=num, num-- );
return sum;
}
The more naïve recursive implementation that performs the addition of after the recursive call, i.e.,
int calc( int num ) {
return num <= 0 ? num : num + calc( num-1 );
}
can't be optimized in this way.

Resources