Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is recursion worse than iteration? [closed]

A few days ago someone said to me that recursion would be better then iteration and should, if possible, always be used.

So, I dove into recursion and tried writing a simple program to get the factorial of a number. This is the recursion:

def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)

and although this works fine, it gets a RuntimeError: maximum recursion depth exceeded as soon as n gets above 997.

So I wrote a simple function that does exactly the same, but with a for loop.

def fact(n):
    a = 1
    for x in range (0, n, 1):
        a = a * (n - x)
    return a

while n < 10000 it gives the answer within 150ms.

So, I though maybe recursion is faster with low numbers, but nope. It takes longer: timing of recursion and iteration

So my question is:
Is there any reason at all to use recursion when writing programs in Python?
and:
Are there any problems that can only be solved with recursion?

like image 803
Nathan Avatar asked Apr 01 '16 09:04

Nathan


People also ask

Is recursion ever better than iteration?

Iteration is faster and more efficient than recursion. It's easier to optimize iterative codes, and they generally have polynomial time complexity. They are used to iterate over the elements present in data structures like an array, set, map, etc.

Why is recursion less efficient than iteration?

Recursion is usually slower than iteration due to the overhead of maintaining the stack. Recursion uses more memory than iteration. Recursion makes the code smaller.

Is recursion slower than iterative?

Recursion has a large amount of overhead as compared to Iteration. It is usually much slower because all function calls must be stored in a stack to allow the return back to the caller functions.

Why is recursion more efficient than iterations?

Overhead: Recursion has a large amount of Overhead as compared to Iteration. Recursion: Recursion has the overhead of repeated function calls, that is due to repetitive calling of the same function, the time complexity of the code increases manyfold. Iteration: Iteration does not involve any such overhead.


2 Answers

There are no problems that need to be solved by explicit recursion; and there are no problems that need to be solved by explicit iteration - Church and Turing have proved that they're interchangeable.

However there are problems that have a neater code, and are easier to reason about if you use recursion. Indeed, Python standard library and even the C code itself uses recursion internally in many places and so is prone to hitting the dreaded recursion limit in many places, for example printing the repr of nested tuples:

>>> from functools import reduce
>>> x = reduce(lambda x, y: (x,), range(10000))
>>> x  # recursion limit hit in C code
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: maximum recursion depth exceeded while getting the repr of a tuple
>>> import pprint
>>> pprint.pprint(x)  # recursion limit hit in Python standard library code.
Traceback (most recent call last):
...
  File "/usr/lib/python3.4/pprint.py", line 390, in _safe_repr
    orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
  File "/usr/lib/python3.4/pprint.py", line 340, in _safe_repr
    if issubclass(typ, dict) and r is dict.__repr__:
RuntimeError: maximum recursion depth exceeded while calling a Python object

You can always convert a recursive algorithm to an iteration with a state machine and stack of intermediate arguments, because after all that's pretty what a CPU does to implement recursion.

like image 115

I can't tell which is faster, but recursion definitely has its place in programming. For example, consider the following function, which is supposed to "flatten" nested lists, into one great big list:

def expand_list(lst):
    result = []
    for element in lst:
        if isinstance(element, list):
            result += expand_list(element)
        else:
            result.append(element)
    return result

(E.g. expand_list([1,2,3,[4,5,[6,7]]]) evaluates to [1,2,3,4,5,6,7])

Iteration wouldn't be able to handle this very well.

(Side note: there are functions in Python to do the same as above function - this was just an example.)

like image 24
acdr Avatar answered Sep 21 '22 17:09

acdr