Chapter 3 - Department of Computer Science
Download
Report
Transcript Chapter 3 - Department of Computer Science
COMPSCI 105 S2 2014
Principles of Computer Science
Recursion 3
Agenda
Agenda
Textbook:
2
The Fibonacci Sequence
The Towers of Hanoi
Binary search
Recursion and efficiency
Problem Solving with Algorithms and Data Structures
Chapter 4 – Recursion
Chapter 5 – Searching
COMPSCI105
22
22.1 The Fibonacci Sequence
The Fibonacci Sequence
Describes the growth of an idealised (biologically
unrealistic) rabbit population, assuming that:
3
Rabbits never die
A rabbit reaches sexual maturity exactly two months after birth,
that is, at the beginning of its third month of life
Rabbits are always born in male-female pairs
At the beginning of every month, each sexually mature malefemale pair gives birth to exactly one male-female pair
COMPSCI105
22
22.1 The Fibonacci Sequence
The Fibonacci Sequence
Problem
How many pairs of rabbits are alive in month n?
Example:
rabbit(5) = 5
1
Month
2
Recurrence relation
rabbit(n) = rabbit(n-1)
+ rabbit(n-2)
3
4
5
4
COMPSCI105
22
22.1 The Fibonacci Sequence
Recursive Definition
Base cases
rabbit(2), rabbit(1)
Recursive
rabbit(n) =
1 if n is 1 or 2
rabbit(n-1) + rabbit(n-2)
Fibonacci sequence
The series of numbers rabbit(1), rabbit(2), rabbit(3), and so on
The sequence of numbers
rabbit(n) for all n is called
Fibonacci Sequence or
Fibonacci numbers.
5
if n > 2
def rabbit(n):
if n <=2:
return 1
return rabbit(n-1) + rabbit(n-2)
COMPSCI105
22
22.1 The Fibonacci Sequence
rabbit(6)
rabbit(6)
return rabbit(5)+rabbit(4)
rabbit(5)
return rabbit(4)+rabbit(3)
rabbit(4)
return rabbit(3)+rabbit(2)
rabbit(3)
return rabbit(2)+rabbit(1)
rabbit(2)
return 1
6
rabbit(2)
return 1
rabbit(4)
return rabbit(3)+rabbit(2)
rabbit(3)
rabbit(3)
return rabbit(2)+rabbit(1) return rabbit(2)+rabbit(1)
rabbit(2)
return 1
rabbit(1)
return 1
rabbit(2)
return 1
rabbit(2)
return 1
rabbit(1)
return 1
rabbit(1)
return 1
COMPSCI105
22
22.1 The Fibonacci Sequence
Examples:
Fibonacci
Spiral
Fibonacci
Tiling
7
COMPSCI105
22
22.2 The Towers of Hanoi
2.6 The Towers of Hanoi
Puzzle consists of n disks and three poles
8
The disks are of different size and have holes to fit
themselves on the poles
Initially all the disks were on one pole, e.g., pole A
The task was to move the disks, one by one, from pole A to
another pole B, with the help of a spare pole C.
Due to its weight, a disks could be placed only on top of
another disk larger than itself
COMPSCI105
22
22.2 The Towers of Hanoi
Solution
If you have only one disk (i.e., n=1),
If you have more than one disk,
simply ignore the bottom disk and solve the problem for n-1
disk, with pole C is the destination and pole B is the spare
Then move the largest disk from pole A to B; then move the n-1
disks from the pole C back to pole B
We can use a recursion with the arguments:
9
move it from pole A to pole B
Number of disks, source pole, destination pole, spare pole
COMPSCI105
22
22.2 The Towers of Hanoi
Solution defifhanoi(count,source,destination,spare):
count is 1:
Move a disk directly from source to destination
Move count-1 disks from source to spare
Applyfrom
function
recursively
Move 1 disk
source
to destination
to
move
these
three
disks.to destination
Move count-1 disk from spare
Source
Source
10
destination
destination
spare
Source
Source
spare
COMPSCI105
destination
destination
spare
spare
22
22.2 The Towers of Hanoi
Pseudo code for the recursive solution
Satisfies the four criteria of a recursive solution
Recursive method calls itself
Each recursive call solves an identical, but smaller problem
Stops at base case
Base case is reached in finite time
def hanoi(count, source, destination, spare):
if count <= 1:
print ("base case: move disk from", source, "to", destination)
else:
1 hanoi(count - 1, source, spare, destination)
2 print ("step2: move disk from", source, "to", destination)
3 hanoi(count - 1, spare, destination, source)
11
COMPSCI105
22
def hanoi(count, source, dest, spare):
if count <= 1:
print ("base case: move disk from", source, "to", dest)
else:
hanoi(count - 1, source, spare, dest)
print ("step2: move disk from", source, "to", dest)
hanoi(count - 1, spare, dest, source)
Example: hanoi(3, "A", "B", "C")
hanoi(3, ‘A’, ‘B’, ‘C’)
Count = 3
Source = A
Dest = B
Spare = C
?
?
hanoi(2, ‘A’, ‘C’, ‘B’)
Count = 2
Source = A
Dest = C
Spare = B
?
3 Steps
3 Steps
?
Print: from A to B
A
B
hanoi(1, ‘A’, ‘B’, ‘C’
Count = 1
Source = A
Dest = B
Spare = C
hanoi(1, ‘B’, ‘C’, ‘A’
Count = 1
Source = B
Dest = C
Spare = A
C
12
3 Steps
Base case:
Print: from A to B
A
B
C
C
Print: from A to C
hanoi(2, ‘C’, ‘B’, ‘A’)
Count = 2
Source = C
Dest = B
Spare = A
?
Check
Animation
B
A
A
B
C
A
B
C
Base case:
Print: from B to C
hanoi(1, ‘C’, ‘A’, ‘B’
Count = 1
Source = C
Dest = A
Spare = B
Base case:
Print: from C
to A
A
B
C
A
B
Print: from C to B
hanoi(1, ‘A’, ‘B’, ‘C’
Count = 1
Source = A
Dest = B
Spare = C
?
COMPSCI105
C
Base case:
Print: from A
to B
22
22.2 The Towers of Hanoi
Call Tree
hanoi(3…) uses 10 calls, a top-level one and 9 recursive calls
hanoi(3, ‘A’, ‘B’, ‘C’)
hanoi(2, ‘A’, ‘C’, ‘B’)
hanoi(2, ‘C’, ‘B’, ‘A’)
Move A -> B
A
B
C
hanoi(1, ‘A’, ‘B’, ‘C’)
hanoi(1 , ‘C’, ‘A’, ‘B’)
Move A -> C
A
B
C
hanoi(1, ‘B’, ‘C’, ‘A’)
A
13
Move C -> B
B
C
A
B
A
C
COMPSCI105
B
C
hanoi(1, ‘A’, ‘B’, ‘C’)
A
B
C
A
C
B
22
22.3 Binary Search
Binary Search
Problem: look for an element (key) in an ordered collection
Sequential search
(e.g. find a word in a dictionary)
Starts at the beginning of the collection
Looks at every item in the collection in order until the item being
searched for is found
Binary search
Cost?
Repeatedly halves the collection and determines which half could
contain the item
Uses a divide and conquer strategy
Search dictionary
OR
Search first half of dictionary
14
Search first half of dictionary
COMPSCI105
22
22.3 Binary Search
Implementation
Implementation issues:
15
How will you pass “half of list” to the recursive calls to
binary_search?
How do you determine which half of the list contains value?
What should the base case(s) be?
How will binary_search indicate the result of the search?
Example: a sorted list
COMPSCI105
22
22.3 Binary Search
Algorithm Design
Base case:
If array is empty number is not in the list, or
If element is the one we look for return it
Recursive call
Determine element in the middle
If the one we look for is smaller than element in the middle then
search in the left half
Otherwise search in the right half of the list
Left half: [first .. mid-1]
0
first
16
1
2
Right half: [mid+1 .. last]
3
4
5
6
mid = (first + last)/2
COMPSCI105
7
8
9
last
22
22.3 Binary Search
Example Code
def binary_search(num_list, first, last, value):
index = 0
if first > last:
index = -1
else:
mid = (first + last) // 2
if value == num_list[mid]:
index = mid
elif value < num_list[mid]:
index = binary_search(num_list, first, mid-1, value)
else:
index = binary_search(num_list, mid+1, last, value)
return index
17
COMPSCI105
22
index
22.3 Binary Search
0
1
2
3
4
5
6
7
Call Tree
1
5
9
12
15
21
29
31
A successful search for 9:
value 9
first 0
last 7
0 7
mid
3
2
value anArray[3]
binary_search(list,0,7,9)
value 9
first 2
last 2
22
mid
2
2
value anArray[2]
binary_search(list,0,2,9)
value 9
first 0
last 2
02
mid
1
2
value anArray[1]
binary_search(list,2,2,9)
return 2
18
COMPSCI105
22
index
22.3 Binary Search
0
1
2
3
4
5
6
7
Call Tree
1
5
9
12
15
21
29
31
An unsuccessful search for 6:
value 6
first 0
last 7
0 7
mid
3
2
value anArray[3]
binary_search(list,0,7,6)
value 6
first 2
last 2
binary_search(list,0,2,6)
value 6
first 0
last 2
02
mid
1
2
value anArray[1]
mid
value anArray[2]
binary_search(list,2,2,6)
binary_search(list,2,1,6)
19
22
2
2
COMPSCI105
value 6
first 2
last 1
first last
return 1
return -1
22
22.4 Efficiency
Recursion and Efficiency
Some recursive solutions are so inefficient that they
should not be used
Factors that contribute to the inefficiency of some
recursive solutions
20
Overhead associated with method calls
Inherent inefficiency of some recursive algorithms
Note: The recursive methods binarySearch and
solveTowers are quite efficient, but the fact and
rabbit are inefficient
COMPSCI105
22
22.4 Efficiency
Recursion and Efficiency
Do not use a recursive solution if it is inefficient and if
you have a clear, efficient iterative solution
Factorial’s recursive solution
Rabbit counting recursive solution
21
Overhead associated with method calls
Iterative method is more efficient
Inherent inefficiency of recursive algorithms
It computes same values over and over again, e.g., rabbit(7)
computes rabbit (3) five times.
Use rabbit’s recurrence relation to construct an efficient
iterative solution
COMPSCI105
22
22.4 Efficiency
Iterative Solution
def iterative_rabbit(n):
previous = 1
current = 1
next_elt = 1
for i in range(3, n+1):
next_elt = current + previous;
previous = current;
current = next_elt
return next_elt
22
COMPSCI105
22
Exercise
Given the following:
my_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
Draw the call tree of
23
binary_search(my_list,0,8,3)
binary_search(my_list,0,8,13)
COMPSCI105
22