And a client would call it like this:// The node structure struct SLLNode { SLLNode *next; int data; }; // Helper function to create a node SLLNode *MakeSLLNode(int Data) { SLLNode *node = new SLLNode; node->data = Data; node->next = 0; return node; }
Output:int main() { SLLNode *sll = BuildSLL(5); // "Magic" function to create a list of length 5 return 0; }
How might you implement BuildSLL(int) iteratively?List: A -> B -> C -> D -> E
Iterative version might look something like this:
SLLNode *BuildSLL_it(int length, char label = 'A')
{
if (length == 0) // quick check
return 0;
SLLNode *node = MakeSLLNode(label++);
SLLNode *head = node;
for (int i = 1; i < length; i++)
{
node->next = MakeSLLNode(label++);
node = node->next;
}
return head;
}
SLLNode *BuildSLL_rec(int length, char label = 'A')
{
if (length == 0) // base case
return 0;
SLLNode *node = MakeSLLNode(label); // build the head
node->next = BuildSLL_rec(length - 1, label + 1); // build the tail
return node;
}
// Build SLL in reverse, iteratively
SLLNode *BuildSLLRev_it(int length, char label = 'A')
{
if (length == 0)
return 0;
SLLNode *head = MakeSLLNode(label++);
for (int i = 1; i < length; i++)
{
SLLNode *node = MakeSLLNode(label++);
node->next = head;
head = node;
}
return head;
}
// Build SLL in reverse, recursively
SLLNode *BuildSLLRev_rec(int length, char label = 'A')
{
if (length == 0)
return 0;
SLLNode *node = MakeSLLNode(label);
return BuildSLLRev_rec_helper(node, length - 1, label + 1);
}
// Helper function for recursion
SLLNode *BuildSLLRev_rec_helper(SLLNode *head, int length, char label = 'A')
{
if (length == 0)
return head;
SLLNode *node = MakeSLLNode(label);
node->next = head;
return BuildSLLRev_rec_helper(node, length - 1, label + 1);
}
It is not uncommon to have helper functions with recursive functions. This is usually because the client (i.e. the user, driver, etc.) isn't going to be passing anything to the function.
For example, suppose you had a singly-linked-list class in C++ called SList. The class might have a public member function named Print that prints out all of the nodes in the list, recursively. The user would simply call it like this:
However, internally, the code would look something like this:list.Print(); // No inputs
The public method simply starts or primes the recursion. The parameter is used so that it can detect when to stop.void SList::Print() const // Public method { Print_rec(head_); // Assume that head_ is a private data member of the SList class } void SList::Print_rec(const SLLNode *node) const // Private helper function { if (node) { cout << node->data << endl; // Print the head Print_rec(node->next); // Print the tail } }
Also, notice how you don't check before making the recursive call:
The check is already in place at the top of the function. This just needlessly complicates things. If that one extra call is too expensive to make, then you shouldn't be using recursion in the first place.void SList::Print_rec(const SLLNode *node) const // Private helper function { if (node) { cout << node->data << endl; if (node->next) // <-------- Don't do this! Print_rec(node->next); } }
Another thing that beginners tend to do is this:
void SList::Print_rec(const SLLNode *node) const // Private helper function { if (node->next) // When node is NULL (and it will be at some point) this is bad! . . . }
Finally, you've got to be careful when using recursion, especially when iteration is just as easy to
implement. (Not always the case.) In the printing example above, it the list is very long, it can easily
overflow the stack with too many recursive calls.