Title: Computer Science 187
1Computer Science 187
Introduction to Programming with Data Structures
Lecture 14 Introduction to Recursion
Announcements
- Programming project 4 is up on the Wiki.
- The next OWL assignment is also available.
- Midterm exam statistics are available on the
ExamS page.
2Definition of Recursive
- Recursive adj. see Recursive
Stan Kelly-Bootle, Devils DP Dictionary
- Circular definitions generally are not useful
- Recursion, where a solution is defined in terms
of itself, is a circular definition that IS
useful. - What makes this work is that we express the
solutions to big problems in terms of the same
solution applied to smaller problems.
3A Humorous(?) Look at Recursion
- A recursive acronym is an acronym which refers to
itself in the expression for which it stands,
similar to a recursive abbreviation. - The earliest example is perhaps the credit card
VISA, which stands for VISA International
Service Association. - Hackers recursive abbreviations
- GNU stands for "GNU's Not Unix!
- PINE stands for "Pine is not Elm
- LAME stands for LAME Ain't an MP3 Encoder
- LAME is a LGPL MP encoder ((Lesser)Gnu Public
Library) - Recursive acronyms appeared in a Dilbert comic
strip, in which Dilbert states that the TTP
project refers to The TTP Project
www.catb.org/esr/jargon Here you can also
find the portrait of J. Random Hacker.
4What is Recursion?
- It is a problem-solving process
- Breaks a problem into identical but smaller
problems - Eventually you reach a smallest problem
- Answer is obvious or trivial
- Using that solution enables you to solve the
previous problems - Eventually the original problem is solved
5Recursive Definitions
- Consider the following list of numbers
- 24, 88, 40, 37
- A list can be defined recursively
- A LIST is a number
- or a number comma LIST
- LIST lt- NUMBER NUMBER , LIST
- That is, a LIST is defined to be a single number,
or a number followed by a comma followed by a
LIST - The concept of a LIST is used to define itself
grammar
6Tracing a Recursive Definition
Assume a list 24,88,40,37
7A Quick Look at a Grammar
- Example simple program grammar
- S gt S S E gt id L gt E
- S gt id E E gt num L gt L, E
- S gt print(L) E gt E E
- E gt E E
- E gt (S, E)
- Source program
- x 3
- print(x, (y 41 x, y))
- Token stream (generated by lexical analysis of
above program) - ID ASSIGN NUM SEMICOLON PRINT LPAREN ID COMMA
LPAREN ID ASSIGN NUM PLUS ID COMMA ID RPAREN
RPAREN - We can demonstrate that this sequence of tokens
forms a word in the language described by the
simple grammar presented above by supplying a
derivation.
OR x 3print(x, (y 41 x, y))
8The Derivation
- A derivation is generated by starting with the
starting non-terminal and repeatedly replacing
each non-terminal by the right-hand side of one
of its productions until only terminal symbols
remain. - S
- S S
- S print(L)
- S print(L, E)
- S print(E, E)
- idE print(E,E)
- idE print(E,(S,E))
- idE print(E,(idE,E))
- idE print(E,(idEE,E))
- idnum print(E,(idEE,E))
- idnum print(id,(idEE,E))
- idnum print(id,(idnumE,E))
- idnum print(id,(idnumE,id))
- idnum print(id,(idnumid,id))
Grammar for Java! http//java.sun.com/docs/books
/jls/second_edition/html/syntax.doc.html
9Recursion
- Recursion - an algorithmic technique, roughly
akin to iteration, that involves
self-invocation of methods. - public static int fac(int N)
-
- if (N lt 0) return 1
- else return (N fac (N-1))
-
-
- public static int fibo(int N)
- if (N 0) return 1
- else if (N 1) return 1
- else return (fibo(N-1) fibo(N-2))
Simplest case
Simpler case
10Rabbits and Fibonacci
- How many pairs of rabbits can be bred from one
pair in one year? - Breed one other pair every month and begin to
breed in the second month after their birth.
1,1,2,3,5,8,13,21,34
Image Sir John Tenniel - 1865 1890 Nursery
Version
http//math.holycross.edu/davids/fibonacci/course
.html
11The Essence of Recursion
- Identify and exploit an identical but smaller
instance of a subproblem in order to solve a big
problem.
- if problem is small enough
- solve it directly
- else
- break into one or more smaller subproblems
- solve each subproblem recursively
- combine results into solution to whole problem
12Problem Solving by Iteration
- If you want to search for a word in a dictionary.
- Could start by searching from A to Z, comparing
each word with the word that is been searched
until the word is found or a word with higher
lexicographic order is found. (Iterative
program). - Sequential search
boolean static seqSearch(intdata,int
target) int index0 boolean found false
while(indexltdata.length !found) found
(dataindextarget) index
index1 return found
13Problem Solving by Recursion
- If you want to search for a word in a dictionary.
- Alternatively, could divide the dictionary in
half, and check in which half of the dictionary
the word is found. Repeat this until the word is
found or two consecutive words are found, where
the first has lower lexicographic order while the
second has higher lexicographic order. (recursive
program). - Binary search
Binary Search MORE ON THIS
LATER 1. If the size of the array is 1, and its
one value is not the one you are looking for,
stop with a "not found" result 2. Select the
middle-point of the array 3. If the value at this
point is the value you are looking for, stop with
a "found it" result 4. If the value is less than
the value in the array at this point, "throw
away" the top half of the array. If the value is
greater than that in the array, "throw away" the
bottom half. 5. Consider this new 1/2-array your
whole array, and go to step 1
Complexity?
14Recursive (Binary) Search
- if the array is empty
- return -1 as the search result (not
present) - else if the middle element target
- return subscript of the middle element
- else if target lt middle element
- recursively search elements before middle
- else
- recursively search elements after the middle
15Adding the squares of numbers from m to n
- given two integers m and n, mltn find
public int sumOfSquares(int m, int n) int i,
sum sum0 for (im iltn i) sum
sum ii return sum
An Iterative Solution.
- pattern is to build solution in stages
- repetitive pattern that enumerates contributions
step by step - combine contributions with a partial solution
that gets closer and closer to the final solution
16Formulating a Recursive Version
- Need a new way of thinking!
- Find a way to solve the overall problems by
breaking it into smaller subproblems. - Constraint is that the smaller subproblems must
be solved the SAME WAY as the larger problem. - Identify the base case(s) that we can solve
directly - Solutions to the subproblems are then combined to
get the overall solution.
This becomes the recursive call.
17Recursion Summary
- In recursive program, there are two components
- The Base Case This is the special case in the
program. Either the solution is found or not
found. But at this point the program always
stops. - The Recursive Case This is the case where the
problem is subdivided in smaller portions.
18Recursion Formulating a Solution
- To find a recursive solution you should ask
yourself - Can you express the problem in terms of a smaller
problem of the same type? - How to reduce the problem space each time you
call the recursive function? - Is there a base case for the problem?
- As you reduce the problem space in each recursive
call, can you reach the base case?
19sumOfSquares recursively
- if (mn)
- there is only one number in the range and the
solution is mm (or nn - same value) - if (m!n)
- the solution is obtained by adding the square of
m to the sum of squares in the range (m1)n
Base Case
Recursive Case
20sumOfSquares recursively
- public int sumOfSquares(int m, int n)
-
- if (mn)
- //solution is the square of m
- else
- //solution is obtained by adding the square
of - //m to the sum of squares in the range
(m1)n.
21sumOfSquares recursively
- public int sumOfSquares(int m, int n)
-
- if (mn)
- return mm //solution is the
square of m - else
- //solution is obtained by adding the square
of - //m to the sum of squares in the range
(m1)n. - return mmsumOfSquares(m1,n)
Base Case
Recursive Case
22Recursive Programming in Java
- A method in Java can invoke itself if set up
that way, it is called a recursive method - Each call sets up a new execution environment,
with new parameters and new local variables - As always, when the method completes, control
returns to the method that invoked it (which may
be another version of itself)
23Adding Integers
- Consider the problem of computing the sum of all
the numbers between 1 and N, inclusive - If N is 5, the sum is
- 1 2 3 4 5 -gt 5 4 3 2 1
- If N is 1, the sum is 1
- This problem can be expressed recursively as
- The sum of 1 to N is N plus the sum of
N-1 to 1
base case
combine
recursion
24Abstractly
25And in Java..
- public int sum (int N)
-
- int result
- if (N 1)
- result 1
- else
- result N sum(N-1)
- return result
Really dumb way of adding up the numbers from 1
to N!
26Visualizing the Recursive Calls
public int sum (int N) int result if (N
1) result 1 else result N
sum(N-1) return result
Method returns
Method invocations
27A Second Example
- Suppose you are given a computer with no integer
multiply, so you want to write a function to do
it. - Suddenly, you remember that multiplication is
nothing more than repeated addition -
multiply(M,N) M multiply(M, N-1)
A Recursive Solution!
28Multiply in Java
- public static int multiply(int m, int n)
-
- if (n 1) return m
- else return m multiply(m, n-1)
-
NOTE
- base, or stopping case N1
- recursive step N gt 1
- notice how multiply appears in second return
- - with parameters
- - an instance of a smaller problem
29How Does It Work?
- In some method int prod multiply(4,3)
12 (final answer)
multiply method invocation
else return 4 multiply(4, 2) 12
else return 4 multiply(4,1) 8
if (1 1) return 4
public static int multiply(int m, int n)
if (n 1) return m else return m
multiply(m, n-1)
30Another View
multiply(5,3)
when done, where do I return to?
else multiply m multiply(5,2) end
make a copy
multiply(5,2)
when done, where do I return to?
else multiply m multiply(5,1) end
make a copy
multiply(5,1)
when done, where do I return to?
then multiply m end
31Factorial Function
- N! N (N-1) (N-2) ...... 1
- N! N (N-1)! recursive def!
- have to define base case 0! 1
public static int factorial(int n) if (n lt
1) return 1 else return n
factorial(n-1)
- Matches mathematical definition of the factorial
function - fac(0) 1
- fac(n) n fac(n-1)
32Simpler Problems
Q What makes factorial(n-1) simpler
than factorial(n) ? A n-1 is closer to the
base case than n. Simpler input
Simpler problem
33Evaluation of factorial(5)
34Pascals Triangle
- The binomial coefficients are the coefficients
that result from the expansion of a binomial
expression of the form (x1)n. - (x1)3 x3 3x2 3x 1 1 3 3 1
- (x1)6 x66x515x420x315x26x1 1 6 15 20
15 6 1 - Also called Pascals triangle
35Recursive Pascals Triangle
1
k0,kn
pascal(n-1,k-1)pascal(n-1,k) otherwise
36Recursive Solution
public int pt(int n, int k) if (we're on one
of the edges) return 1 else return
the sum of the two parents
37Pascals Triangle
1 1 1 1 2
1 1 3 3 1 1 4 6 4
1 1 5 10 10 5 1 . . . . . . . . . .
. . . . . . . . .
pt(n, 0) 1 for all n pt(n, n) 1 for all n
pt(n, m) pt(n-1,k-1) pt(n-1,k)
38Recursive Solution
public int pt(int n, int k) if (k n k
0) return 1 else return
pt(n-1,k-1) pt(n-1,k)
double recursion
39Recursion Versus Iteration
- Recursion and iteration are similar
- Iteration
- Loop repetition test determines whether to exit
- Recursion
- Condition tests for a base case
- Can always write iterative solution to a problem
solved recursively, but - Recursive code often simpler than iterative
- Thus easier to write, read, and debug
40Tail Recursion ? Iteration
- When recursion involves single call that is at
the end ... - It is called tail recursion and it easy to make
iterative - public static int iterFact (int n)
- int result 1
- for (int k 1 k lt n k)
- result result k
-
- return result
41Efficiency of Recursion
- Recursive method often slower than iterative
why? - Overhead for loop repetition smaller than
- Overhead for call and return
- If easier to develop algorithm using recursion,
- Then code it as a recursive method
- Software engineering benefit probably outweighs
... - Reduction in efficiency
- Dont optimize prematurely!
42End
43Another version of sumOfSquares
- int sumOfSquares(int m, int n)
-
- if (nm) return nn
- else
- return nnsumOfSquares(m,n-1)
Very similar except instead of going up from m,
we go down from n
44One More
- int sumOfSquares(int m, int n)
-
- if (mn) return mm
- else
-
- int middle (mn)/2
- return sumOfSquares(m,middle)
- sumOfSquares(middle1, n)
-
45The Evaluation Tree(middle version)