Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do recursive functions have a minimum space complexity of O(N)?

I was thinking about recursive functions. Take a simple function, for example one to print a linked list recursively:

void print(list *list){
  if(list){
     cout << list->data
     print(list->next);
  }
}

At first this seems like a pretty innocuous function, but isn't it storing an address (labeled by the variable list) in every stack frame? Assume there is no tail-call optimization. We need space for N addresses, where N is the size of the list. The space needed grows linearly in proportion to the size of the list.

I can't think of how you would implement a recursive function without having at least one local variable or argument stored on the stack. So, it seems as though every recursive function is going to have at best linear space complexity. If this is the case, then wouldn't it almost always be advisable to use iteration over recursion?

like image 633
ordinary Avatar asked Nov 17 '13 07:11

ordinary


2 Answers

While all non-optimized function calls can be assumed to consume a stack frame, it's not always the case that a recursive algorithm that operates on N elements will require a stack O(N) in size.

A recursive tree-traversal algorithm uses O(lg N) stack frames, for example, as does a recursive QuickSort.

like image 163
Gabe Avatar answered Oct 06 '22 20:10

Gabe


You're right, the space complexity of the piece of code is linear in the size of the list, assuming no tail call optimization.

In general, recursion will make things a little slower and more memory hungry, yes. But you can't always asymptotically improve on this by implementing it iteratively, since for non-tail recursive functions, you will need to manually maintain the stack anyway in an iterative implementation, so you will still use the same amount of memory.

Think of a depth first traversal. You will need to store each node on the stack, together with which child you need to visit next, so that after you return from visiting one of its children, you know which node to go to next. Recursion makes this very easy, since it abstracts all the ugly bookkeeping. An iterative implementation will not be asymptotically better, and I'd expect the practical differences to be very, very little as well.

A lot of times, recursion makes things easier without sacrificing anything. In your case, there is no point for it - it's just a pedagogical example of recursion.

like image 43
IVlad Avatar answered Oct 06 '22 21:10

IVlad