What is Recursive Function/Method, How to use it in .NET?
What is Recursive Function/Method?
Functions are not necessarily invoked by other functions. A function can call itself too. When a function calls itself, it's a recursive function.
A recursive has two specifications:
1. Recursive function may call itself so many times but limited.
2. Recursive function has parameter(s) and calls itself with new parameters.
Why Recursive?
All methods with while and if, can be written as recursive.
Recursive solution is a powerful and simple approach for complicated developments, but it can worsen performance because of using call stack again and again. (Sometimes scandal performance)
The use of recursive, in C# is not only possible, but also necessary sometimes.
I'm going to give examples to show how to use recursive function/method.
1. The Factorial:
We know that the factorial (!) of a positive integer number is the product of all positive integers less than or equal to the number.
0! = 1
1! = 1
2! = 2 * 1! = 2
3! = 3 * 2! = 6
...
n! = n * (n - 1)!
The following code is a method to compute the Factorial (no recursive):
public long Factorial(int n)
{
if (n == 0)
return 1;
long value = 1;
for (int i = n; i > 0; i--)
{
value *= i;
}
return value;
}
Computing the Factorial by a recursive method:
public long Factorial(int n)
{
if (n == 0)
return 1;
return n * Factorial(n - 1);
}
2. The Fibonacci numbers:
The Fibonacci numbers are the numbers in the following sequence:
0,1,1,2,3,5,8,13,21,34,55,…
If F0 = 0 and F1= 1 then:
Fn = Fn-1 + Fn-2
The following code is a method to compute Fn (no recursive, hard code, high performance):
public long Fib(int n)
{
if (n < 2)
return n;
long[] f = new long[n+1];
f[0] = 0;
f[1] = 1;
for (int i = 2; i <= n; i++)
{
f[i] = f[i - 1] + f[i - 2];
}
return f[n];
}
If we use recursive method, our code will be more simple, but a very poor performance:
public long Fib(int n)
{
if (n == 0 || n == 1)
return n;
return Fib(k - 2) + Fib(k - 1);
}
3. Boolean Compositions:
Sometimes solving the problem is more complicated than the Fibonacci. For example we want to show all possible compositions for n Boolean variables. In other words, if n = 3, then we must have the following output:
true, true, true
true, true, false
true, false, true
true, false, false
false, true, true
false, true, false
false, false, true
false, false, false
Solving this problem without a recursive function is not so easy and not simple, when we have quantities for n.
public void CompositionBooleans(string result, int counter)
{
if (counter == 0)
return;
bool[] booleans = new bool[2] { true, false };
for (int j = 0; j < 2; j++)
{
StringBuilder stringBuilder = new StringBuilder(result);
stringBuilder.Append(string.Format("{0} ", booleans[j].ToString())).ToString();
if (counter == 1)
MessageBox.Show(stringBuilder.ToString());
CompositionBooleans(stringBuilder.ToString(), counter - 1);
}
}
Now, we can use and call this method:
CompositionBoolean(string.Empty, 3);
Or, for observing encapsulation, we can define another overload:
public void CompositionBooleans(int counter)
{
CompositionBooleans(string.Empty, counter);
}
private void CompositionBooleans(string result, int counter)
{
if (counter == 0)
return;
bool[] booleans = new bool[2] { true, false };
for (int j = 0; j < 2; j++)
{
StringBuilder stringBuilder = new StringBuilder(result);
stringBuilder.Append(string.Format("{0} ", booleans[j].ToString())).ToString();
if (counter == 1)
MessageBox.Show(stringBuilder.ToString());
CompositionBooleans(stringBuilder.ToString(), counter - 1);
}
}
4. InnerExceptions:
Recursive methods are useful for getting the last innerException:
public Exception GetInnerException(Exception ex)
{
return (ex.InnerException == null) ? ex : GetInnerException(ex.InnerException);
}
This code:
return (ex.InnerException == null) ? ex : GetInnerException(ex.InnerException);
is abridgment of and equivalent to the following code:
if (ex.InnerException == null)
return ex;
return GetInnerException(ex.InnerException);
Now, when we have an exception, we can find the last innerException of the exception. For example:
try
{
throw new Exception("This is the exception",
new Exception("This is the first inner exception.",
new Exception("This is the last inner exception.")));
}
catch (Exception ex)
{
MessageBox.Show(GetInnerException(ex).Message);
}
Consequently:
We can use iterative algorithms instead of recursive and have better performance but we may also have time expense and hard code. The point is we have to choose the best approach which depends on situations.
Recommendations:
- I am addressing beginners, but it doesn't mean that I am also a beginner.
- About Boolean Compositions, Ian Shlasko has a better Idea:
public void BooleanCompositions(int count) { BooleanCompositions(count - 1, "true"); BooleanCompositions(count - 1, "false"); } private void BooleanCompositions(int counter, string partialOutput) { if (counter <= 0) Console.WriteLine(partialOutput); else { BooleanCompositions(counter - 1, partialOutput+ ", true"); BooleanCompositions(counter - 1, partialOutput+ ", false"); } }
Good luck