Instructors and textbooks frequently use two common examples to introduce recursion. The text presents both examples as rules, functions, and C++ functions. A third bonus example illustrates elegant, recursive solutions for visiting or traversing the nodes in a binary tree.
The factorial function frequently appears in combinatorial and permutation problems. It is only defined on integers, but the gamma function (not covered here) extends the factorial function to real numbers.
0! = 1 (base case) n! = 1 * 2 * 3 * . . . * (n - 1) * n
\[ f(n) = \left\{ \begin{array}{ll} 1 & , n = 0 \\ n(n-1) & , n \gt 0 \\ \end{array} \right. \]
#include <iostream> using namespace std; int fact(int n) { if (n > 0) return n * fact(n - 1); // recursion else return 1; // non-recursion (base case) } int main() { cout << fact(10) << endl; return 0; }
Few number sequences can match the ubiquitousness of the Fibonacci numbers, which appear everywhere from architecture to biology (see Fibonacci Sequence at Math Is Fun). Can you see how the function implements the rule for forming the Fibonacci sequence?
x0 = 0 (base case) x1 = 1 (base case) xn = xn-1 + xn-2
\[ x_n = \left\{ \begin{array}{ll} 0 & , n = 0 \\ 1 & , n = 1 \\ x_{n-1} + x_{n-2} & , n \gt 1 \\ \end{array} \right. \]
#include <iostream> using namespace std; int fib(int n) { if (n == 0) return 0; // base case else if (n == 1) return 1; // base case else return fib(n - 1) + fib(n - 2); // recursion } int main() { cout << fib(10) << endl; return 0; }
We explored binary trees in chapter 4 as one use of pointers. We can use binary trees again to demonstrate recursion.
![]() |
struct node { Data d; node* left; node* right; }; void display(Data d); |
(a) | (b) |
The structure specification and the function prototype are sufficient to write a set of small, simple, and quite elegant recursive functions that display the data in a binary tree.
Inorder | Preorder | Postorder |
---|---|---|
void visit(node* n) { if (n->left != nullptr) visit(n->left); display(n->d); if (n->right != nullptr) visit(n->right); } |
void visit(node* n) { display(n->d); if (n->left != nullptr) visit(n->left); if (n->right != nullptr) visit(n->right); } |
void visit(node* n) { if (n->left != nullptr) visit(n->left); if (n->right != nullptr) visit(n->right); display(n->d); } |
(a) | (b) | (c) |
enum { INORDER, PREORDER, POSTORDER }; ... void visit(node* n, int order) { if (order == PREORDER) display(n->d); if (n->left != nullptr) visit(n->left, order); if (order == INORDER) display(n->d); if (n->right != nullptr) visit(n->right, order); if (order == POSTORDER) display(n->d); }