I know basic definition of recursive function.....but i want to know its impact on memory?? Why it is not chosen over loop or iteration?
-
For the responders: I see a bunch on "recursion sucks if not TCO", etc, but in many problems I have dealt with, the level of recursion is trivially small (and stack "allocations" are quite cheap). Just another thing to factor into response.user166390– user1663902010-12-02 06:36:42 +00:00Commented Dec 2, 2010 at 6:36
7 Answers
It's usually not chosen for one of two reasons:
- the coder doesn't understand recursion (in particular, tail-end optimisation); and
- it can be expensive on stack space.
Although the standard has nothing to say about stack space, it's often a limited resource prone to overflow.
For example, this is a bad recursive function:
def addTwoPositiveNumbers (a,b):
if b == 0:
return a
return addTwoPositiveNumbers (a+1,b-1)
(unless it can do that tail end optimisation). That's because it can theoretically use a lot of stack levels, for example when b = 1,000,000,000, it will use a billion stack frames.
On the other hand a binary search is not too bad since it removes half the search space with each level of recursion. So even if you had a billion entries, that would only be log21,000,000,000 or 30 stack levels.
Having listed the reasons why I think people avoid it, I should say that I use it quite a bit and you should realise that many problems are naturally expressed better as a recursive solution. The code is cleaner and more readable. For that reason alone, it should be a part of your arsenal.
5 Comments
+ function (time complexity is different).C++ does not mandate tail call optimization, so recursive functions that can trivially be converted to loops may still take up space linear in the call depth (storing the frame).
Additionally, C/C++ does not necessarily detect stack overflow, so that's another problem with potentially deep calls.
EDITED to have more qualified language ("necessarily")
EDIT
Some people seem hung up over the fact that specific compilers such as gcc and clang perform tail call optimization and/or stack overflow detection. The point is, if it is not mandated, then it is unsafe. For example, gcc only performs tail call optimization at -O2, -O3 and -Os. So, if the program depends on tail call optimization being performed, the program will mysteriously die when someone compiles without an optimization flag (on gcc).
If it is good programming practice, then, by all means, they can continue to write programs that depend on compiler flags. Or ones that depend on compilers. Optimization not optional.
8 Comments
You can always rewrite recursion with an iterative operation - the question becomes one of readability/easiness of implementation. And for quite a few problems, recursion leads to simpler algorithm (e.g. most stuff related to graph/tree).
As far as memory goes: in a language like C or C++, every function call needs to push its arguments to the calling stack. This stack has a limited size (having a 100-long chain of calls is almost always ok - 1000000 almost certainly not). The exact limitation are highly system dependent.
More high level languages, especially functional ones, have "tricks" to enable for stack which seem "infinite" in some cases (tail calls, which are pretty common cases). Such languages often guarantees the optimization, called Tail Call Optimization (TCO), which enable for elegant code in cases where recursion makes sense.
Comments
Recursion is often avoided because of the stack overflow issue. Iterative solutions don't have that problem and all recursive problems can be rewritten to use iteration (some more easily than others). In addition, many programmers simply aren't that familiar with recursion (it doesn't turn up that often)--someone maintaining code later on may not understand what's going on and make a modification which screws something up. That's generally a bad thing. Recursion in other languages, particularly functional ones, is often seen more frequently, due to how they handle it.
Comments
Recursive functions are usually avoided because
- It may take too much of gray cells
- It may take too much of stack space than what is desirable/permissible.
They also may have undesirable consequences if the function is not reentrant.
3 Comments
Unless the compiler can optimize recursive calls out (tail-recursion optimization) each invokation needs a copy of all parameters and local variables plus the return address. That stuff has to be stored somewhere which is usually on the stack. So impact is amount of memory for one invokation multiplied by the number of subsequent invokations.
Also when invokation goes deep down into recursion newer egions of stack are occupied and this can causes cache misses which can slow down execution and can also be attributed as memory impact.
Comments
Think about how the recursion actually works, and the impact on memory is clear. Start by understanding how function calling in general works. You might want to start here.