|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionOriginaly posted at blogs.microsoft.co.il/blogs/Eyal Recursive functions – is a function that partially defined by itself and consists of some simple case with a known answer. Example: Fibonacci number sequence, factorial function, quick sort and more. Iterative functions – are loop based imperative repetition of a process (in contrast to recursion which has more declarative approach). Comparison between Iterative and Recursive approaches from performance considerationsFactorial: //recursive function calculates n!
static int FactorialRecursive(int n)
{
if (n <= 1) return 1;
return n * FactorialRecursive(n - 1);
}
//iterative function calculates n!
static int FactorialIterative(int n)
{
int sum = 1;
if (n <= 1) return sum;
while (n > 1)
{
sum *= n;
n--;
}
return sum;
}
As we can clearly see the recursive is a lot slower than the iterative (considerably) and limiting (stackoverflow). The reason for the poor performance is heavy push-pop of the registers in the ill level of each recursive call. Fibonacci: //--------------- iterative version ---------------------
static int FibonacciIterative(int n)
{
if (n == 0) return 0;
if (n == 1) return 1;
int prevPrev = 0;
int prev = 1;
int result = 0;
for (int i = 2; i <= n; i++)
{
result = prev + prevPrev;
prevPrev = prev;
prev = result;
}
return result;
}
//--------------- naive recursive version ---------------------
static int FibonacciRecursive(int n)
{
if (n == 0) return 0;
if (n == 1) return 1;
return FibonacciRecursive(n - 1) +
FibonacciRecursive(n - 2);
}
//--------------- optimized recursive version ---------------------
static Dictionary
As before the recursive approach is worse than iterative however, we could apply memoization pattern (saving previous results in dictionary for quick key based access), although this pattern isn't match for iterative approach (but definitely improvement over the simple recursion). Notes1. The calculations may be wrong in big numbers, however the algorithms should be correct. 2. For timer calculations i used System.Diagnostics.Stopwatch. Points of Interest1. Try not to use recursion in system critical locations. 2. Elegant solutions not always the best performing when used in "recursive situations". 3. If you required to use recursion at least try to optimize it with dynamic programming approaches (such as memoization) HistoryPost: November 06, 2007
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||