Recursion And Iteration
December 5, 2017
Today’s exercise is about basic programming techniques.
Your task is to pick a function and write two versions of it, one recursive, the other iterative; compare the two versions on readability, programming ease, speed, and any other criteria that are important to you. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
In Python, a Fib implemenation. Seems like iterative is a lot faster, but didn’t really optimize the recursive one that much either.
@Rutger: Your algorithms are not the same. The recursive algorithm takes exponential time, the iterative algorithm takes linear time. You might enjoy this program, which is recursive and takes logarithmic time:
I am a big fan of recursion but, to give the iterative version a
bit more credit, it can be rewritten as follows, avoiding both
the temporary variable and the mutations.
I suppose someone may object that this version is thinly veiled
recursion but another could counter that tail recursion is
thinly veiled iteration. Perhaps more to the point, both the
following version and the two versions in the solution generate
iterative processes in Scheme (to use SICP terminology if I
recall correctly), although two of them are iterative programs
and one recursive.
Rutger: The first algorithm is actually horribly bad: it’s exponential, because all the smaller Fibonacci numbers are recomputed over and over. If you make it recursive with memoization, it’s linear but can still blow up your stack due to the recursion if n is large.
@chaw: You don’t need min and max. If m < n, the first call swaps them.
I used the temporary variable in the iterative version on purpose, because it is needed in languages that don’t allow simultaneous assignment.
A tail call is just a goto combined with a simultaneous reassignment of local variables. The reassignment part can make code clearer and less error-prone (since we are less likely to forget to modify a variable appropriately) but really both are just different ways of expressing the same underlying computation.
Converting a non-tail recursion into an iterative form can be interesting though. Here’s the naive fibonacci implementation, in Javascript:
Neither recursive call is in tail position, but we can build up the final result in an accumulating parameter, passed between the two calls:
Now one call is in tail position and can fix the other with an explicit continuation function:
To get properly iterative, we can replace the continuation functions with a stack (containing the stored values of n), use an explicit loop and in-place modification everywhere:
As people have observed, this is still a terrible way to compute the fibonacci numbers.
Here’s a solution in Java for serializing an XML tree. The iterative version uses a stack.
Output:
It appears there was a problem in the html code i pasted.
Here’s another attempt, this time escaping the angle brackets with backslashes.
Output:
Here’s another attempt, this time adding “sourcecode” markup.
SerializeIterative:
SerializeRecursive: