lec15-recursion
lec15-recursion
Fundamental Computing
with C++
Recursion
Fall, 2024
What is Recursion?
2
Basic Elements of Recursion
• A recursive function is a function that contains a call
to itself either directly or indirectly
• It can be considered an advanced form of control flow,
an alternative to iteration/repetition
int foo(…) {
…
… foo(…) …; // Calls itself
…
}
4
Counting Down (Iterative):
Example
• Suppose we need to write a function that counts
down from 𝑁 (> 0) to 1, printing 𝑁, … , 2,1 in turn
An iterative 1 #include <iostream>
solution: 2 using namespace std;
3
4 void countDown(int n) {
5 for (int i = n; i > 0; i--)
6 cout << i << endl;
7 }
8 5
9 int main() { 4
10 countDown(5); 3
11 return 0; 2
12 } 1
5
Counting Down (Recursion):
Example
• A recursive solution:
• If 𝑁 < 1, then do nothing and done!
• If 𝑁 ≥ 1, then the solution consists of two sub-tasks:
i. Print 𝑁; and
ii. Count down from 𝑁 − 1 to 1
7
Tracing Recursion
void countDown(int n) {
if (n >= 1) {
int main() { cout << n << endl;
countDown(5); countdown( n - 1 );
return 0; } // else nothing
} }
cout << 5 << endl;
countdown( 4 );
cout << 4 << endl;
countdown( 3 );
cout << 3 << endl;
countdown( 2 );
5 cout << 2 << endl;
4 countdown( 1 );
3 cout << 1 << endl;
2 countdown( 0 );
1 (Do nothing!) 8
Iteration vs Recursion
Iteration Recursion
(while, do-while, for)
• Maintains and modifies loop • Keeps producing simpler
variables in a termination versions of the original
condition problem
• Until the condition is met • Until some base cases are
reached
void countDown(int n) { void countDown(int n) {
for (int i = n; i > 0; i--) if (n >= 1) {
cout << i << endl; cout << n << endl;
} countdown(n - 1);
} // else nothing
}
9
Summation 1 + 2 + ⋯ + 𝑛:
Example
𝑛
• To compute:
𝑖 = 1 + 2 + 3 + ⋯+ 𝑛
𝑖=1
= 1 + 2 + ⋯+ 𝑛 − 1 +𝑛
𝑛−1
11
Summation 1 + 2 + ⋯ + 𝑛:
Example
summation(5)
Recursive
→ 5 + summation(4)
calls
→ 5 + (4 + summation(3))
→ 5 + (4 + (3 + summation(2)))
→ 5 + (4 + (3 + (2 + summation(1))))
→ 5 + (4 + (3 + (2 + 1)))
Combining
solution
→ 5 + (4 + (3 + 3))
→ 5 + (4 + 6)
int summation(int n) {
→ 5 + 10 if (n == 1)
→ 15 return 1;
else
return n + summation(n - 1);
} 12
String Reversal: Example
• rev("abcde") → “edcba”
• rev("CSCI1357") → “7531ICSC”
• Reversing an empty string gets an empty string
• Reversing a non-empty string gets…
1 string rev(string s) { rev("abcde")
2 if (s == "") → rev("bcde") + 'a'
3 return "";
4 else
5 return rev(s.substr(1)) + s.at(0);
6 }
𝑁 disks 𝑁=4
Peg 1 Peg 2 Peg 3
15
Tower of Hanoi
• The goal is to move the 𝑁 disks from peg 1 to peg 3
satisfying the following constraints:
• Only one disk can be moved at a time
• A larger disk cannot be on top of a smaller disk
(Move
disks)
17
Tower of Hanoi: Recursion
• Solution for 𝑁 > 1: (Recursive case)
“Step” 1 “Step” 3
Step 2
Move one
Step 2
disk from Peg
1 to Peg 3
Recursion
Move 𝑁 − 1 disks
from Peg 2 to Peg 3
“Step” 3
Peg 1 Peg 2 Peg 3 Peg 1 Peg 2 Peg 3
19
Tower of Hanoi Solution Original peg
Destination peg
1 void hanoi(int n, int from, int to, int buffer) {
2 if ( n == 1 ) { “Middle” peg
3 cout << from << " --> " << to << endl;
4 } else {
5 hanoi(n - 1, from, buffer, to); // "Step" 1
6 cout << from << " --> " << to << endl; // Step 2
7 hanoi(n - 1, buffer, to, from); // "Step" 3
8 }
9 }
10
11 int main() {
12 int n;
13 cout << "Enter n: ";
14 cin >> n;
15 hanoi(n, 1, 3, 2); // From peg 1 to 3 via 2
16 return 0;
17 } 20
Enter n: 5↵
1 --> 3
1 --> 2
3 --> 2
Tower of Hanoi Solution 1 -->
2 -->
3
1
2 --> 3
1 --> 3
1 --> 2
Enter n: 1↵ Enter n: 4↵ 3 --> 2
1 --> 3 1 --> 2 3 --> 1
2 --> 1
1 --> 3 3 --> 2
Enter n: 2↵ 2 --> 3 1 --> 3
1 --> 2 1 --> 2 1 --> 2
1 --> 3 3 --> 1 3 --> 2
2 --> 3 1 --> 3
3 --> 2 2 --> 1
1 --> 2 2 --> 3
Enter n: 3↵ 1 --> 3
1 --> 3 2 --> 1
1 --> 3
2 --> 3 3 --> 2
1 --> 2
2 --> 1 3 --> 1
3 --> 2 2 --> 1
3 --> 1
1 --> 3 2 --> 3
2 --> 3 1 --> 3
2 --> 1
1 --> 2 1 --> 2
2 --> 3 3 --> 2
1 --> 3
1 --> 3 1 --> 3
2 --> 3 2 --> 1
2 --> 3
1 --> 3 21
Tower of Hanoi: 𝑁 = 3
void hanoi(int n, int from, int to, int buffer) { Enter n: 3↵
if ( n == 1 ) { 1 --> 3
cout << from << " --> " << to << endl; 1 --> 2
} else { 3 --> 2
hanoi(n - 1, from, buffer, to); // "Step" 1 1 --> 3
cout << from << " --> " << to << endl; // Step 2 2 --> 1
hanoi(n - 1, buffer, to, from); // "Step" 3 2 --> 3
} 1 --> 3
}
hanoi(3, 1, 3, 2); (3 disks, Peg 1 to 3 via 2)
Enter n: 3↵
Peg 1 Peg 2 Peg 3 1 --> 3
1 --> 2
3 --> 2
1 --> 3
1→3 2 --> 1
Peg 1 Peg 2 Peg 3 2 --> 3
1 --> 3
1→2
Peg 1 Peg 2 Peg 3
3→2
Peg 1 Peg 2 Peg 3 23
Tower of Hanoi: 𝑁 = 3
1→3 Enter n: 3↵
Peg 1 Peg 2 Peg 3 1 --> 3
1 --> 2
3 --> 2
1 --> 3
2→1 2 --> 1
Peg 1 Peg 2 Peg 3 2 --> 3
1 --> 3
2→3
Peg 1 Peg 2 Peg 3
1→3 Done!
Peg 1 Peg 2 Peg 3 24
Tower of Hanoi: 𝑁 = 4
hanoi(4, 1, 3, 2); (4 disks, Peg 1 to 3 via 2)
Enter n: 4↵
1 --> 2 hanoi(1, 1, 2, 3);
1 --> 3 hanoi(2, 1, 3, 2);
2 --> 3 hanoi(1, 2, 3, 1);
1 --> 2 hanoi(3, 1, 2, 3);
3 --> 1 hanoi(1, 3, 1, 2);
3 --> 2 hanoi(2, 3, 2, 1);
1 --> 2 hanoi(1, 1, 2, 3);
1 --> 3
2 --> 3 hanoi(1, 2, 3, 1);
2 --> 1 hanoi(2, 2, 1, 3);
3 --> 1 hanoi(1, 3, 1, 2);
2 --> 3 hanoi(3, 2, 3, 1);
1 --> 2 hanoi(1, 1, 2, 3);
1 --> 3 hanoi(2, 1, 3, 2);
2 --> 3 hanoi(1, 2, 3, 1);
25
Pitfall of Recursion
• Recursive function calls incur both time and
memory overheads since a runtime stack must be
maintained for the function calls
26
Tower of Hanoi
• It has been proved that a Tower of Hanoi of 𝑁 disks
can be solved in 2𝑁 − 1 moves
• 3 disks → 7 moves
• 4 disks → 15 moves
…
• 10 disks → 1,023 moves
…
• 64 disks → 18,446,744,073,709,551,615 moves
27
Fibonacci Series: Example
• The Fibonacci Series
28
Fibonacci Series: Recursion
0 𝑛=0
𝑓𝑖𝑏(𝑛) = ቐ 1 𝑛=1
𝑓𝑖𝑏 𝑛 − 2 + 𝑓𝑖𝑏(𝑛 − 1) 𝑛≥2
fib(0) + fib(1)
30
Non-Recursive Fibonacci (Iteration)
1 long long fib( int n ) {
2 long long fibN, fibN1, fibN2;
3
4 if (n == 0) {
5 return 0;
6 } else if (n == 1) {
7 return 1;
8 } else {
9 fibN1 = 0;
10 fibN2 = 1;
11 for (int cnt = 2; cnt <= n; cnt++) {
12 fibN = fibN1 + fibN2; // Get the next fib num
13 fibN1 = fibN2;
14 fibN2 = fibN;
15 }
16 return fibN;
17 }
18 } 31
When (Not) to Use Recursion?
• In general, use recursion if:
32
Summary
• Recursive functions have the following elements
• Different cases are governed by selection (if-else)