CH # 3 (Recursion)
CH # 3 (Recursion)
Introduction to Recursion:
A function is recursive if a statement in the body of the function calls itself. Recursion is
the process of defining something in terms of itself. For a computer language to be
recursive, a function must be able to call itself.
Properties
A recursive function can go infinite like a loop. To avoid infinite running of recursive
function, there are two properties that a recursive function must have −
Base criteria − There must be at least one base criteria or condition, such that, when this
condition is met the function stops calling itself recursively.
Progressive approach − The recursive calls should progress in such a way that each time
a recursive call is made it comes closer to the base criteria.
For example, let us consider the function factr() shown below, which computers
the factorial of an integer. #include <stdio.h>
int factorial (int);
main()
{
int num, fact;
printf (“Enter a positive integer value: ");
scanf (“%d”, &num);
fact = factorial (num);
printf ("\n Factorial of %d =%5d\n", num, fact);
}
if (n == 0)
return (result);
else
{
for (i=1; i<=n; i++)
result = result * i;
}
return (result);
}
The operation of the non-recursive version is clear as it uses a loop starting at 1 and
ending at the target value and progressively multiplies each number by the moving
product.
When a function calls itself, new local variables and parameters are allocated storage on
the stack and the function code is executed with these new variables from the start. A
recursive call does not make a new copy of the function. Only the arguments and
variables are new. As each recursive call returns, the old local variables and parameters
are removed from the stack and execution resumes at the point of the function call inside
the function.
When writing recursive functions, you must have a exit condition somewhere to force the
function to return without the recursive call being executed. If you do not have an exit
condition, the recursive function will recurse forever until you run out of stack space and
indicate error about lack of memory, or stack overflow.
1. Time Complexity
In case of iterations, we take number of iterations to count the time complexity. Likewise,
in case of recursion, assuming everything is constant, we try to figure out the number of
times a recursive call is being made. A call made to a function is Ο(1), hence the (n)
number of times a recursive call is made makes the recursive function Ο(n).
2. Space Complexity
Space complexity is counted as what amount of extra space is required for a module to
execute. In case of iterations, the compiler hardly requires any extra space. The compiler
keeps updating the values of variables used in the iterations. But in case of recursion, the
system needs to store activation record each time a recursive call is made. Hence, it is
considered that space complexity of recursive function may go higher than that of a
function with iteration.
When the factorial function is first called with, say, N = 5, here is what happens:
FUNCTION: Does N = 0? No Function Return Value = 5 * factorial (4)
At this time, the function factorial is called again, with N = 4.
FUNCTION: Does N = 0? No Function Return Value = 4 * factorial (3) At this time, the
function factorial is called again, with N = 3.
FUNCTION: Does N = 0? No Function Return Value = 3 * factorial (2)
At this time, the function factorial is called again, with N = 2.
FUNCTION: Does N = 0? No Function Return Value = 2 * factorial (1) At this time, the
function factorial is called again, with N = 1. FUNCTION: Does N = 0? No Function
Return Value = 1 * factorial (0) At this time, the function factorial is called again, with N
= 0. FUNCTION: Does N = 0? Yes Function Return Value = 1
Now, we have to trace our way back up! See, the factorial function was called six
times. At any function level call, all function level calls above still exist! So, when we
have N = 2, the function instances where N = 3, 4, and 5 are still waiting for their
return values.
So, the function call where N = 1 gets retraced first, once the final call returns 0. So,
the function call where N = 1 returns 1*1, or 1. The next higher function call, where N
= 2, returns 2 * 1 (1, because that's what the function call where N = 1 returned). You
just keep working up the chain.
When N = 2, 2 * 1, or 2 was returned.
When N = 3, 3 * 2, or 6 was returned.
When N = 4, 4 * 6, or 24 was returned.
When N = 5, 5 * 24, or 120 was returned.
And since N = 5 was the first function call (hence the last one to be recalled), the value
120 is returned.
A recursive definition for the Fibonacci sequence of integers may be defined as follows:
Fib (n) = n if n = 0 or n = 1
Fib (n) = fib (n-1) + fib (n-2) for n >=2
We will now use the definition to compute fib(5):