1. Recursion Basics
What is Recursion?
A function (or procedure) is recursive if it calls itself within the function.
Key Point: There's a special type called tail-recursion which calls itself only once and in the last statement. Tail recursion is very similar to a do-while loop.
Factorial Example
n! = {1 if n = 0, 1*2*3*...*(n-1)*n if n > 0}
Recursive: n! = {1 if n = 0, (n-1)!*n if n > 0}
Iterative Solution:
int Factorial(int n) {
int fact = 1;
for(int count = 2; count <= n; count++)
fact = fact * count;
return fact;
}
Recursive Solution:
int Factorial(int n) {
if (n==0) return 1;
else return n * Factorial(n-1);
}
Structure Comparison
While-Loop vs Recursion vs Tail-Recursion
While: condition → loop-body → jump back
Recursion: condition → part 1 → recursive call → part 2
Tail-Recursion: condition → part 1 → recursive call
3. Sorting Algorithms
Insertion Sort using Fantastic Four
1
Size-n problem: int* sorting(int *A, int n);
2
Stopping condition: n == 1, return address of A
3
Size-m problem: m = n-1, assume first n-1 elements sorted
4
Solution: Insert element x at correct position in sorted array
Time Complexity Comparison
| Sorting Algorithm |
Average-case |
Worst-case |
| Insertion Sort |
O(n²) - Slow |
O(n²) |
| Mergesort |
O(n lg n) - Fast |
O(n lg n) |
| Quicksort |
O(n lg n) - Fastest |
O(n²) |
4. Hanoi Towers
Problem Description
Move n disks from source to destination using center as temporary, following rules:
- Only move one disk at a time
- Larger disk cannot be placed on smaller disk
Recursive Solution
void hanoitowers(int n, char *S, char *M, char *D) {
if (n == 1) {
cout << "move top from " << S << " to " << D << endl;
}
else {
hanoitowers(n - 1, S, D, M); // size-(n-1) problem
hanoitowers(1, S, M, D); // size-1 problem
hanoitowers(n - 1, M, S, D); // size-(n-1) problem
}
}
Following the Four Steps
1
Size-n: void Hanoi(n, source, center, destination)
2
Stopping: n = 1, "Move disk from source to destination"
3
Size-(n-1): Two cases needed for this problem
4
Solution: Move n-1 to center, move bottom to dest, move n-1 from center to dest
6. Binary Search Trees (BST)
Data Structure Definition
struct treeNode {
int data; // also called key
struct treeNode *left, *right; // pointers to treeNode
}
struct treeNode *root = NULL; // global pointer to root
Tree Traversal Algorithms
Inorder Traversal
inorderTraverse(p) {
if p ≠ 0 then
inorderTraverse(p->left);
print(p->data);
inorderTraverse(p->right);
}
Result: left subtree - root - right subtree
Preorder Traversal
preorderTraverse(p) {
if p ≠ 0 then
print(p->data);
preorderTraverse(p->left);
preorderTraverse(p->right);
}
Result: root - left subtree - right subtree
Postorder: left subtree - right subtree - root
Analogy: Tree postorder = print after recursive calls, Linked list preorder = print forward, postorder = print backward
Search Function
struct treeNode * search(struct treeNode *top, int key) {
struct treeNode *p = top;
if (key == p->data)
printf("data = %d\n", p->data);
if (key < p->data) {
if (p->left == NULL) return p;
else return search(p->left, key);
}
else {
if (p->right == NULL) return p;
else return search(p->right, key);
}
return p;
}
Insertion Algorithm
void insertion() {
struct treeNode *p, *q;
int i, n, key;
printf("Enter the number of entries you want to insert\n");
scanf("%d", &n);
for (i=0; idata = key;
p->left = NULL; p->right = NULL;
if (root == NULL) root = p; // tree empty
else {
q = search(root, key);
if (key <= q->data) q->left = p;
else q->right = p;
}
}
}
7. Complexity Analysis Summary
Search Algorithm Complexity
- Linear search: O(n) for data in arrays or linked lists
- Binary search: O(log₂n) if the binary tree is balanced
- Unbalanced BST: Could degenerate to O(n) (like a linked list)
Improving Search Speed
- Make tree balanced: Requires restructuring (Red-Black tree)
- Allow more children: k-ary search tree with O(log_k n) performance
- Best performance: Google BigTable uses advanced tree structures
Remember: The choice between recursion and iteration often depends on the problem structure. Recursion is elegant for tree operations and divide-and-conquer algorithms, while iteration might be more efficient for simple repetitive tasks.
CSE 240 - Introduction to Programming Languages | Arizona State University
This cheat sheet covers Module 5: Recursion and Data Structures