2 types of recursion exist:
Tail | Non-Tail |
void Tail(int i) | void NonTail(int i) |
Tail Recursion
- The simplest case. A glorified loop.
- Can simply be replace by iterative method.
- The basic idea behind Tail Recursion is to eliminate the storage of any state information across the recursive steps. All information that would ever be needed at any single step is passed as a parameter to the function instead of being stored at some higher level in the recursion stack.
- In tail recursion, the recursive call should be the ONLY last statement, and there should be no earlier recursive calls whether direct or indirect.
- Used to implement loops in languages that do not support loop structures explicitly (e.g. prolog).
Example convert Tail recursion to iterative:
for loop syntax
for(init; condition; increment)
statement;
Tail | Iterative |
void Tail(int i) | void Tail(int i) |
Tail Recursion Examples:
public static void f1(int n)
{
Console.WriteLine(n);
if(n > 0)
f1(n - 1); //last statement with recursive call
}
public static void f3(int n)
{
if(n > 6)
{
Console.WriteLine(2*n);
f3(n – 2); //last statement with recursive call
} else if(n > 0)
{
Console.WriteLine(n);
f3(n – 1); //last statement with recursive call
}
}
Non - Tail recursion
Non Tail | Iterative |
double Power(double x, int n) | double Power(double x, int n) |
string Reverse(string s) | string Reverse(string s) |
Converting Non – Tail Recursion to Tail Recursion
- A non-tail recursive method can often be converted to a tail-recursive method by means of an "auxiliary" parameter. This parameter (A.K.A Accumulator) is used to form the result.
- The idea is to attempt to incorporate the pending operation into the auxiliary parameter in such a way that the recursive call no longer has a pending operation.
- The technique is usually used in conjunction with an "auxiliary" method. This is simply to keep the syntax clean and to hide the fact that auxiliary parameters are needed.
Non Tail | Tail |
long Factorial (int n) | long Factorial(int n) |
int Fib(int n){ | int Fib (int n) { |
Common errors
- Post increment and decrement operators must not be used since the update will not occur until AFTER the method call - infinite recursion.
public static int SumArray (int[ ] x, int index)
{
if (index == x.length)return 0;
else
return x[index] + SumArray (x, index++);
}
- Local variables must not be used to accumulate the result of a recursive method. Each recursive call has its own copy of local variables.
public static int sumArray (int[ ] x, int index)
{
int sum = 0;
if (index == x.length)return sum;
else {
sum += x[index];
return sumArray(x,index + 1);
}
}
- Wrong placement of return statement.
incorrect version (always return initial pass in result)
public static int Sum(int n, int result)
{
if (n >= 0)
Sum(n - 1, n + result);
return result;
}
correct version:
public static int Sum(int n, int result)
{
if (n == 0)
return result;
else
return Sum(n-1, n + result);
}
No comments:
Post a Comment