Recursion Review

(related reading: Main & Savitch, Chapter Nine)

Functions that call themselves

int fact(int n)
{
  if (n < 2) 
    return 1;
  else
  return (n * (fact(n-1)));
}

Data structures that refer to themselves

class ListNode {
public:
  // ... constructors, member functions ...
  size_t length();
private: 
  int val;
  ListNode *next;
  // ... maybe other member variables ...

};

Recursive functions and data structures together

size_t ListNode::length()
{
  if (next == NULL)
    return 1;
  else
  return (1 + next->length());
}

Recursive member functions

When member functions are called, the object invoking the member function is implicitly passed in as an argument. For class C, it is as if all member functions have an argument of the form const C* X. We can think of ListNode::length() as:
size_t length(const ListNode* X)
{
  if (X->next == NULL)
    return 1;
  else
  return (1 + length(X->next));
}
(In fact, in C++ the implicit pointer to the object has a name --- this.)

Recursion vs. iteration

We probably would write ListNode::length iteratively:
size_t ListNode::length()
{
  size_t i=1;

  for(ListNode *p=next; p!=NULL; p=p->next)
    i++;
  return i;
}
The iterative version is very similar to the recursive version. Observe that they both run in O(n) --- linear time. This is not a coincidence. The linked-list structure is also linear --- the items are stored in a straight line.

Nonlinear data structures

Thus far, we focused on linear data structures: arrays and linked lists. Now we begin to look at nonlinear data structures.

Two important facts about functions acting on nonlinear data structures: