unit 5a recursion: introduction15110-n15/lectures/unit05-1-recursion.pdf · unit 5a recursion:...

53
UNIT 5A Recursion: Introduction 1 IN ORDER TO UNDERSTAND RECURSION, ONE SHOULD FIRST UNDERSTAND RECURSION.

Upload: hoangquynh

Post on 24-Apr-2018

228 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

UNIT 5A Recursion: Introduction

1

IN ORDER TO UNDERSTAND RECURSION,

ONE SHOULD FIRST UNDERSTAND RECURSION.

Page 2: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Announcements

• First written exam next week Wednesday

• All material from beginning is fair game

– There are sample exams on the resources page

2

Page 3: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Last time

• Iteration: repetition with variation

• Linear search

• Insertion sort

• A first look at time complexity (measure of efficiency)

3

Page 4: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

This time

• Introduction to recursion

• What it is

• Recursion and the stack

• Recursion and iteration

• Examples of simple recursive functions

• Geometric recursion: fractals

4

Page 5: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

5

Recursion

The Loopless Loop

Page 6: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion

• A recursive function is one that calls itself. def i_am_recursive(x) : maybe do some work if there is more work to do : i_am_recursive(next(x)) return the desired result

• Infinite loop? Not necessarily, not if next(x) needs less work than x.

3

Page 7: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive Definitions

Every recursive function definition includes two parts:

– Base case(s) (non-recursive) One or more simple cases that can be done right away

– Recursive case(s) One or more cases that require solving “simpler” version(s) of the original problem.

• By “simpler”, we mean “smaller” or “shorter” or “closer to the base case”.

4

Page 8: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Example: Factorial

• n! = n × (n-1) × (n-2) × … × 1 2! = 2 × 1 3! = 3 × 2 × 1 4! = 4 × 3 × 2 × 1

• alternatively: 0! = 1 (Base case) n! = n × (n-1)! (Recursive case) So 4! = 4 × 3! 3! = 3 × 2! 2! = 2 × 1! 1! = 1 × 0!

5

Page 9: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion conceptually

6

4! = 4(3!) 3! = 3(2!) 2! = 2(1!) 1! = 1 (0!)

Base case make smaller instances

of the same problem

Page 10: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion conceptually

7

4! = 4(3!) 3! = 3(2!) 2! = 2(1!) 1! = 1 (0!) = 1(1) = 1

Compute the base case

make smaller instances

of the same problem

Page 11: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion conceptually

8

4! = 4(3!) 3! = 3(2!) 2! = 2(1!) = 2 1! = 1 (0!) = 1(1) = 1

Compute the base case

make smaller instances

of the same problem

build up

the result

Page 12: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion conceptually

9

4! = 4(3!) 3! = 3(2!) = 6 2! = 2(1!) = 2 1! = 1 (0!) = 1(1) = 1

Compute the base case

make smaller instances

of the same problem

build up

the result

Page 13: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursion conceptually

10

4! = 4(3!) = 24 3! = 3(2!) = 6 2! = 2(1!) = 2 1! = 1 (0!) = 1(1) = 1

Compute the base case

make smaller instances

of the same problem

build up

the result

Page 14: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive Factorial in Python

# 0! = 1 (Base case)

# n! = n × (n-1)! (Recursive case)

def factorial(n):

if n == 0: # base case

return 1

else: # recursive case

return n * factorial(n-1)

11

Page 15: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

15

Inside Python Recursion

factorial(4)? S

T

A

C

K

n=4

Page 16: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

16

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

n=4

Page 17: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

17

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)?

n=4

n=3

Page 18: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

18

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

n=4

n=3

Page 19: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

19

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)?

n=4

n=3

n=2

Page 20: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

20

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)? = 2 * factorial(1)

n=4

n=3

n=2

Page 21: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

21

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)? = 2 * factorial(1)

factorial(1)?

n=4

n=3

n=2

n=1

Page 22: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

22

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)? = 2 * factorial(1)

factorial(1)? = 1 * factorial(0)

n=4

n=3

n=2

n=1

Page 23: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

23

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)? = 2 * factorial(1)

factorial(1)? = 1 * factorial(0)

factorial(0) = 1

n=4

n=3

n=2

n=1

n=0

Page 24: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

24

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2)? = 2 * factorial(1)

factorial(1) = 1 * 1 = 1

n=4

n=3

n=2

n=1

Page 25: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

25

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3)? = 3 * factorial(2)

factorial(2) = 2 * 1 = 2

n=4

n=3

n=2

Page 26: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

26

Inside Python Recursion

factorial(4)? = 4 * factorial(3) S

T

A

C

K

factorial(3) = 3 * 2 = 6

n=4

n=3

Page 27: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

27

Inside Python Recursion

factorial(4) = 4 * 6 = 24 S

T

A

C

K

n=4

Page 28: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive vs. Iterative Solutions

• For every recursive function, there is an equivalent iterative solution.

• For every iterative function, there is an equivalent recursive solution.

• But some problems are easier to solve one way than the other way.

• And be aware that most recursive programs need space for the stack, behind the scenes

12

Page 29: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Factorial Function (Iterative)

def factorial(n): result = 1 # initialize accumulator var for i in range(1, n+1): result = result * i return result

13

def factorial(n): if n == 0: # base case return 1 else: # recursive case return n * factorial(n-1)

Versus (Recursive):

Page 30: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

A Strategy for Recursive Problem Solving (hat tip to Dave Evans)

• Think of the smallest size of the problem and write down the solution (base case)

• Now assume you magically have a working function to solve any size. How could you use it on a smaller size and use the answer to solve a bigger size? (recursive case)

• Combine the base case and the recursive case

14

Page 31: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

31

Iteration to Recursion: exercise

• Mathematicians have proved π2/6 = 1 + 1/4 + 1/9 + 1/16 + ...

We can use this to approximate π Compute the sum, multiply by 6, take the square root

def pi_series_iter(n) : result = 0 for i in range(1, n+1) : result = result + 1/(i**2) return result def pi_approx_iter(n) : x = pi_series_iter(n) return (6*x)**(.5)

Let's convert this to a

recursive function

(see file pi_approx.py

for a sample solution.)

Page 32: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

32

Recursion on Lists

• First we need a way of getting a smaller input from a larger one:

– Forming a sub-list of a list:

32

>>> a = [1, 11, 111, 1111, 11111, 111111]

>>> a[1:] [11, 111, 1111, 11111, 111111]

>>> a[2:] [111, 1111, 11111, 111111]

>>> a[3:] [1111, 11111, 111111]

>>> a[3:5] [1111, 11111]

>>>

the "tail" of list a

Page 33: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive sum of a list

def sumlist(items):

if items == []:

15

The smallest size list is the

empty list.

Page 34: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive sum of a list

def sumlist(items):

if items == []:

return 0

15

Base case:

The sum of an empty list is 0.

Page 35: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive sum of a list

def sumlist(items):

if items == []:

return 0

else:

15

Recursive case:

the list is not empty

Page 36: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive sum of a list

def sumlist(items):

if items == []:

return 0

else:

...sumlist(items[1:])...

15

What if we already know the

sum of the list's tail?

Page 37: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive sum of a list

def sumlist(items):

if items == []:

return 0

else:

return items[0] + sumlist(items[1:])

15

What if we already know the

sum of the list's tail? We can

just add the list's first element!

Page 38: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Tracing sumlist

>>> sumlist([2,5,7])

sumlist([2,5,7]) = 2 + sumlist([5,7])

5 + sumlist([7])

7 + sumlist([])

0

16

def sumlist(items): if items== []: return 0 else: return items[0] + sumlist(items[1:])

After reaching the base case, the final result is built up by the computer by adding 0+7+5+2.

Page 39: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

39

List Recursion: exercise

• Let's create a recursive function rev(items)

• Input: a list of items

• Output: another list, with all the same items, but in reverse order

• Remember: it's usually sensible to break the list down into its head (first element) and its tail (all the rest). The tail is a smaller list, and so "closer" to the base case.

• Soooo… (picture on next slide) 39

Page 40: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Reversing a list: recursive case

40

See file rev_list.py

Page 41: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

41

Multiple Recursive Calls

• So far we've used just one recursive call to build up our answer

• The real conceptual power of recursion happens when we need more than one!

• Example: Fibonacci numbers

41

Page 42: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Fibonacci Numbers

• A sequence of numbers: 0 1 1 2 3 5 8 13 ... 17

+ +

+

+ +

+

Page 43: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Fibonacci Numbers in Nature

• 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, etc.

• Number of branches on a tree, petals on a flower, spirals on a pineapple.

• Vi Hart's video on Fibonacci numbers (http://www.youtube.com/watch?v=ahXIMUkSXX0)

18

Page 44: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive Definition

Let fib(n) = the nth Fibonacci number, n ≥ 0

– fib(0) = 0 (base case)

– fib(1) = 1 (base case)

– fib(n) = fib(n-1) + fib(n-2), n > 1

20

def fib(n): if n == 0 or n == 1: return n

else: return fib(n-1) + fib(n-2)

Two recursive calls!

Page 45: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Recursive Call Tree

22

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)

1

2

5

1 0

1 1

2

1 0

1

3

1 0

1

fib(0) = 0

fib(1) = 1

fib(n) = fib(n-1) + fib(n-2), n > 1

Page 46: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Iterative Fibonacci def fib(n): x = 0 next_x = 1 for i in range(1,n+1): x, next_x = next_x, x + next_x return x

23

Faster than the

recursive version.

Why?

simultaneous

assignment

Page 47: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Geometric Recursion (Fractals)

• A recursive operation performed on successively smaller regions.

24

Sierpinski's

Triangle

http://fusionanomaly.net/recursion.jpg

Page 48: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Sierpinski’s Triangle

25

Page 49: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Sierpinski’s Carpet

26

Page 50: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

(the next slide shows an animation that could give some people

headaches)

50

Page 51: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Mandelbrot set

51

Source: Clint Sprott, http://sprott.physics.wisc.edu/fractals/animated/

Page 52: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

52

Fancier fractals

Page 53: UNIT 5A Recursion: Introduction15110-n15/lectures/unit05-1-Recursion.pdf · UNIT 5A Recursion: Introduction 1 ... def factorial(n): result = 1 # initialize accumulator var ... Fibonacci

Now, Binary Search

32

recursion for search

image: Matt Roberts, http://people.bath.ac.uk/mir20/blogposts/bst_close_up.php