82
This document is copyright (C) Stanford Computer Science and Nick Troccoli, licensed under Creative Commons Attribution 2.5 License. All rights reserved. Based on slides created by Keith Schwarz, Julie Zelenski, Jerry Cain, Eric Roberts, Mehran Sahami, Stuart Reges, Cynthia Lee, Marty Stepp, Ashley Taylor and others. CS 106X, Lecture 8 More Recursion reading: Programming Abstractions in C++, Chapters 7-8

CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

This document is copyright (C) Stanford Computer Science and Nick Troccoli, licensed under Creative Commons Attribution 2.5 License. All rights reserved.Based on slides created by Keith Schwarz, Julie Zelenski, Jerry Cain, Eric Roberts, Mehran Sahami, Stuart Reges, Cynthia Lee, Marty Stepp, Ashley Taylor and others.

CS 106X, Lecture 8More Recursion

reading:Programming Abstractions in C++, Chapters 7-8

Page 2: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

2

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 3: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

3

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 4: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

4

Recursive Thinking•In code, recursion is when a function in your

program calls itself as part of its execution.•Conceptually, a recursive problem is one that is

self-similar; it can be solved via smaller occurrences of the same problem.

Page 5: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

5

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 6: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

6

Example 1: Factorialn! = n * (n-1) * (n-2) * (n-3) * … * 1

• Write a function that computes and returns the factorial of a provided number, recursively (no loops).– e.g. factorial(4) should return 24– You should be able to compute the value of any non-negative number.

(0! = 1).

Page 7: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

7

Factorial// Returns n!, or 1 * 2 * 3 * 4 * ... * n.// Assumes n >= 0.int factorial(int n) {

if (n < 0) { // error handlingthrow "illegal negative n";

if (n == 0) { // base casereturn 1;

} else {return n * factorial(n - 1); // recursive case

}}

Page 8: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

8

Recursive Program StructurerecursiveFunc() {if (test for simple case) { // base caseCompute the solution without recursion

} else { // recursive caseBreak the problem into subproblems of the same formCall recursiveFunc() on each self-similar subproblemReassamble the results of the subproblems

}}

Page 9: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

9

Example 2: Fibonacci0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...• The Fibonacci sequence starts with 0 and 1, and each subsequent

number is the sum of the two previous numbers.• Write a function that computes and returns the nth Fibonacci

number, recursively (no loops).– e.g. fibonacci(6) should return 8

Page 10: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

10

Fibonacci// Returns the i’th Fibonacci number in the sequence

// (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …)

// Assumes i >= 0.

int fibonacci(int i) {

if (i < 0) { // error handling

throw "illegal negative index";

else if (i == 0) { // base case 1

return 0;

} else if (i == 1) { // base case 2

return 1;

} else {

// recursive case

return fibonacci(i-1) + fibonacci(i-2); }

}

Page 11: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

11

Recursive Treefibonacci(4)

fibonacci(3) fibonacci(2)

fibonacci(2) fibonacci(1)

fibonacci(1) fibonacci(0)

fibonacci(1) fibonacci(0)

Base case Recursive case

Page 12: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

12

isPalindrome exercise• Write a recursive function isPalindrome accepts a string and

returns true if it reads the same forwards as backwards.

isPalindrome("madam") ® trueisPalindrome("racecar") ® trueisPalindrome("step on no pets") ® trueisPalindrome("able was I ere I saw elba") ® trueisPalindrome("Q") ® trueisPalindrome("Java") ® falseisPalindrome("rotater") ® falseisPalindrome("byebye") ® falseisPalindrome("notion") ® false

isPalindrome

Page 13: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

13

isPalindrome solution// Returns true if the given string reads the same// forwards as backwards.// By default, true for empty or 1-letter strings.bool isPalindrome(string s) {

if (s.length() < 2) { // base casereturn true;

} else { // recursive caseif (s[0] != s[s.length() - 1]) {

return false;}string middle = s.substr(1, s.length() - 2);return isPalindrome(middle);

}}

Page 14: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

14

isPalindrome solution 2// Returns true if the given string reads the same// forwards as backwards.// By default, true for empty or 1-letter strings.// This version is also case-insensitive.bool isPalindrome(string s) {

if (s.length() < 2) { // base casereturn true;

} else { // recursive casereturn tolower(s[0]) == tolower(s[s.length() - 1])

&& isPalindrome(s.substr(1, s.length() - 2));}

}

Page 15: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

15

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 16: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

16

reverseLines exerciseWrite a recursive function reverseLines that accepts a file input stream and prints the lines of that file in reverse order.

Example input file:I am not a person who contributesAnd I refuse to believe thatI will be useful

Expected console output:I will be usefulAnd I refuse to believe thatI am not a person who contributes

"I Have a Dream" by Antonia Lee, Sara Fung, Christy Fung, Rachel Lam http://poets.spice.org.hk/index.php?option=com_content&view=article&id=45:my-family&catid=6:reverse-poem&Itemid=7

Page 17: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

17

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 18: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

18

Reversal pseudocodeReversing the lines of a file:• If the input stream is empty:

– Stop• If there are lines left:

– Read the next line L– Print the rest of the lines in reverse order– Print the line L.

Page 19: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

19

reverseLines solutionvoid reverseLines(ifstream& input) {

string line;if (!getline(input, line)) {

// base case – stop} else {

// recursive casereverseLines(input);cout << line << endl;

}

}if (x) {

do nothing} else {

do something}

if (not x) {do something

}

Page 20: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

20

reverseLines solutionvoid reverseLines(ifstream& input) {

string line;if (getline(input, line)) {

// recursive casereverseLines(input);cout << line << endl;

}}

– Where is the base case?

Page 21: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

21

output:input file:I am not a person who contributesAnd I refuse to believe thatI will be useful

I will be usefulAnd I refuse to believe thatI am not a person who contributes

Tracing our algorithm• call stack: The function invocations running at any one time.

reverseLines(input);void reverseLines(ifstream& input) { // call 1

string line;if (getline(input, line)) {// "I am not a person who contributes"

reverseLines(input); // make call 2, waitcout << line << endl;

}}

void reverseLines(ifstream& input) { // call 2string line;if (getline(input, line)) {// "And I refuse to believe that"

reverseLines(input); // make call 3, waitcout << line << endl;

}}

void reverseLines(ifstream& input) { // call 3string line;if (getline(input, line)) { // "I will be useful"

reverseLines(input); // make call 4, waitcout << line << endl;

}}

void reverseLines(ifstream& input) { // call 4string line;if (getline(input, line)) { // fail

reverseLines(input);cout << line << endl;

}}

Page 22: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

22

The “Recursive Leap of Faith"• When writing a recursive function, pretend that someone has

already written a function that can solve that problem for smaller inputs. How could you use it in your implementation?

• E.g. “what if we had a function that could print out a smaller file in reverse?”

void reverseLines(ifstream& input) {string line;if (getline(input, line)) {

reverseLines(input); // "leap of faith"cout << line << endl;

}}

Page 23: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

23

The “Recursive Leap of Faith"

https://www.youtube.com/watch?v=VgolfyRO-RI

Page 24: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

24

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 25: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

25

Recursion & Big-Ovoid reverseLines(ifstream& input) {

string line;if (getline(input, line)) {

reverseLines(input);cout << line << endl;

}}

• What is the Big-O of the above function?• (What is N?)

How many times is this function called in total?

What is the runtime of each individual function call?x

Page 26: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

26

Recursion & Big-Ovoid reverseLines(ifstream& input) {

string line;if (getline(input, line)) {

reverseLines(input);cout << line << endl;

}}

reverseLines([3])

reverseLines([2])

reverseLines([1])

reverseLines([0])

There is one recursive call for each line of the file.

The runtime of an individual function call is O(1).

Thus, the total runtime is O(N)*O(1) = O(N).

Page 27: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

27

Fibonacci: Big-Ofibonacci(4)

fibonacci(3) fibonacci(2)

fibonacci(2) fibonacci(1)

fibonacci(1) fibonacci(0)

fibonacci(1) fibonacci(0)

• Each recursive call makes 2 additional recursive calls.• The worst-case depth of the recursion is the index of the Fibonacci

number we are trying to calculate (N).• Therefore, the number of total calls is O(2N).• Each individual function call does O(1) work. Therefore, the total

runtime is O(2N) * O(1) = O(2N).

Page 28: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

28

Recursion & Big-O• The runtime of a recursive function is the number of function calls

times the work done in each function call.• The number of calls for a branching recursive function is usually

!(#$)where– b is the worst-case branching factor (# recursive calls per function

execution)– d is the worst-case depth of the recursion (the longest path from the

top of the recursive call tree to a base case).

Page 29: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

29

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 30: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

30

Announcements• Computer Forum Career Fair TODAY until 4PM @ Packard Lawn• Candy poll!• HW1 IGs

Page 31: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

31

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 32: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

32

Recursive Treefibonacci(4)

fibonacci(3) fibonacci(2)

fibonacci(2) fibonacci(1)

fibonacci(1) fibonacci(0)

fibonacci(1) fibonacci(0)

As we recurse, we do extra work recomputing some Fibonacci numbers many times!

Page 33: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

33

Recursive Treefibonacci(4)

fibonacci(3) fibonacci(2)

fibonacci(2) fibonacci(1)

fibonacci(1) fibonacci(0)

Is there a way to remember what we already computed?

Page 34: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

34

Memoization• memoization: Caching results of previous expensive function calls

for speed so that they do not need to be re-computed.– Often implemented by storing call results in a collection.

• Pseudocode template:cache = {}. // initially emptyfunction f(args):

if I have computed f(args) before:Look up f(args) result in cache.

else:Actually compute f(args) result.Store result in cache.

Return result.

Page 35: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

35

Memoized Fibonacci// Returns the nth Fibonacci number (no error handling).// This version uses memoization.int fibonacci(int i, Map<int, int>& cache) {

if (i < 2) {return i;

} else if (cache.containsKey(i)) {return cache[i];

} else {int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 36: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

36

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);int fibonacci(int i, Map<int, int>& cache) { // i=5

if (i < 2) {return i;

} else if (cache.containsKey(i)) {return cache[i];

} else {int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

Page 37: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

37

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 38: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

38

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 39: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

39

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 40: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

40

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 41: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

41

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 42: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

42

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 43: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

43

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 44: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

44

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=1if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 45: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

45

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=1if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 46: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

46

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1

Page 47: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

47

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=0if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 48: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

48

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=0if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 49: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

49

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1 0

Page 50: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

50

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 1

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1 0

Page 51: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

51

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 1

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1

Page 52: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

52

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 1

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=1if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 53: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

53

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 1

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=1if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 54: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

54

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 1

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1 1

Page 55: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

55

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

1 1

Page 56: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

56

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

2

Page 57: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

57

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

2

Page 58: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

58

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 59: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

59

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=2if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 60: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

60

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 2

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

2 1

Page 61: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

61

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 3

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=4if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

2 1

Page 62: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

62

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 3

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

3

Page 63: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

63

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 3

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 64: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

64

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 3

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

int fibonacci(int i, Map<int, int>& cache) { // i=3if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 65: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

65

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 3

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

3 2

Page 66: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

66

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache);

2 -> 13 -> 24 -> 35 -> 5

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

int fibonacci(int i, Map<int, int>& cache) { // i=5if (i < 2) {

return i;} else if (cache.containsKey(i)) {

return cache[i];} else {

int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

3 2

Page 67: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

67

Memoized Stack TraceMap<int, int> cache;int sixthFibonacci = fibonacci(5, cache); // 5

2 -> 13 -> 24 -> 35 -> 5

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

call tree

Page 68: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

68

Memoized Fibonacci

2 -> 13 -> 24 -> 35 -> 5

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

Cached Recurse Skipped

Page 69: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

69

Memoized Fibonacci

2 -> 13 -> 24 -> 35 -> 5

cache

fib(5)

fib(4) fib(3)

fib(3) fib(2)

fib(2) fib(1)

fib(2) fib(1)

fib(1) fib(0)

fib(1) fib(0) fib(1) fib(0)

What is the runtime of this function?

O(2N) is technically correct for worst-case, but we can be more precise.

The branch factor for the memoized version becomes 1, because once we calculate fib(n-1), fib(n-2) will always be cached. Thus, the runtime is O(n)!

Page 70: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

70

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Page 71: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

71

Wrapper Functions

• The above function signature isn’t ideal; it requires the client to know to pass in an (empty) map.

• In general, the parameters we need for our recursion will not always match those the client will want to pass.

• Is there a way we can remove that requirement, while still memoizing?

• YES! A “wrapper” function is a function that “wraps” around the first call to a recursive function to abstract away any additional parameters needed to perform the recursion.

Map<int, int> cache;int sixthFibonacci = fibonacci(5, cache); // 5

Page 72: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

72

That’s a Wrap(per)!// “Wrapper” function that returns the nth Fibonacci number.// This version calls the recursive version with an empty cache.int fibonacci(int i) {

HashMap<int, int> cache;return fibonacci(i, cache);

}

// Recursive function that returns the nth Fibonacci number.// This version uses memoization.int fibonacci(int i, HashMap<int, int>& cache) {

if (i < 0) {throw "Illegal negative index";

} else if (i < 2) {return i;

} else if (cache.containsKey(i)) {return cache[i];

} else {int result = fibonacci(i-1, cache) + fibonacci(i-2, cache);cache[i] = result;return result;

}}

Page 73: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

73

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 74: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

74

crawl exercise• Write a function crawl that accepts a file name as a parameter and

prints information about that file.– If the name represents a normal file, just print its name.– If the name represents a directory, print its name and information

about every file/directory inside it, indented.

coursehandouts

syllabus.doclecture-schedule.xls

homework1-gameoflife

life.cpplife.hGameOfLife.pro

– recursive data: A directory can contain other directories.

crawl

Page 75: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

75

Stanford C++ files#include "filelib.h"

Function DescriptioncreateDirectory(name) creates a a new directory with given path namedeleteFile(name) removes file from diskfileExists(name) whether this file exists on the diskgetCurrentDirectory() returns directory the current C++ program runs ingetExtension(name) returns file's extension, e.g. "foo.cpp"® ".cpp"getHead(name),getTail(name)

separate a file path into the directory and file part;for "a/b/c/d.txt", head is "a/b/c", tail is "d.txt"

isDirectory(name) returns whether this file name represents a directoryisFile(name) returns whether this file name represents a regular filelistDirectory(name, v) fills the given Vector<string> with the names of all

files contained in the given directoryreadEntireFile(name, v) reads lines of the given file into a vector of stringsrenameFile(old, new) changes a file's name

Page 76: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

76

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 77: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

77

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 78: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

78

Wrapper FunctionsWe cannot vary the indentation without an extra parameter:

void crawl(string filename, string indent) {

This doesn’t match the function signature we must implement, so we need to use a wrapper function.

Page 79: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

79

The Recursion ChecklistqFind what information we need to keep track of.

What inputs/outputs are needed to solve the problem at each step? Do we need a wrapper function?

qFind our base case(s). What are the simplest (non-recursive) instance(s) of this problem?

qFind our recursive step. How can this problem be solved in terms of one or more simpler instances of the same problem that lead to a base case?

qEnsure every input is handled. Do we cover all possible cases? Do we need to handle errors?

Page 80: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

80

crawl solution// Wrapper to print out this file and everything in it.void crawl(const string& filename) {

crawl(filename, "");}

// Prints information about this file recursively,// and (if it is a directory) any files inside it.void crawl(const string& filename, const string& indent) {

cout << indent << getTail(filename) << endl;if (isDirectory(filename)) {

// recursive case; print contained files/dirsVector<string> filelist;listDirectory(filename, filelist);for (string subfile : filelist) {

crawl(filename + "/" + subfile,indent + " ");

}}

}

Page 81: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

81

Default ParametersWe could also use a default parameter in this case:

void crawl(const string& filename, const string& indent = "") {cout << indent << getTail(filename) << endl;if (isDirectory(filename)) {

// recursive case; print contained files/dirsVector<string> filelist;listDirectory(filename, filelist);for (string subfile : filelist) {

crawl(filename + "/" + subfile,indent + " ");

}}

}

But for the purposes of this example we’ll stick with a wrapper function. Sometimes default parameters can do the trick, but not always – e.g. if we need to pass by reference, or initialize a data structure dynamically).

Page 82: CS 106X, Lecture 8 More Recursion - Stanford University · 2018-10-13 · 17 The Recursion Checklist qFind what information we need to keep track of. What inputs/outputs are needed

82

Plan For Today• Recap: Recursion So Far• More Practice: Reversing a File• Recursion: Runtime• Announcements• Memoization• Wrapper Functions

Next time: fractals (Recursion you can see!)