Title: CS 112 Introduction to Programming
1CS 112 Introduction to Programming
- Lecture 29
- Recursive Programming
- Richard Yang
2Outline
- Admin. and review
- Recursive thinking defining concept recursively
- Recursive method calls
- Places of recursion matter
3Admin.
- Assignment 6 is returned
- All the unpicked up assignments are outside of my
office at Watson 202 - Assignment 7
- How to convert a char to a String?char
wordString myStr new String(word)
4Review Java GUI Programming
- GUI components
- Components e.g. Button, Label
- Containers, e.g. Frame, Panel
- A container has a layout manager, which manages
how components in it are laid out - e.g., Flow, Border, Grid, Box
- Often you will need to use multiple containers to
achieve desired effects - Components can generate events to which listener
objects can respond - Add a listener to a component when an event
happens, the method of the listener object is
automatically invoked - We often use one listener object to serve
multiple components, if the components are
similar - e.g., use getSource() to determine the component
generating the event.
5Recursive Programming
- Recursion a method calls itself
- Recursion is often used to search for a solution
to a problem, e.g., - Hanoi Towers how to move the disks?
- Maze search how to find a way out of a maze?
- Change maker how many ways of making changes to
a one-dollar bill? - Recursion is also useful for writing elegant
programs, e.g., - KochSnowflake
6Outline
- Admin. and review
- Recursive thinking defining concept recursively
- Recursive method calls
- Places of recursion matter
7Recursive Thinking
- A recursive definition is one which uses the word
or concept being defined in the definition itself - When defining an English word, a recursive
definition is often not helpful - Good is not bad, bad is no good.
- But in other situations, a recursive definition
can be an appropriate way to express a concept - Before applying recursion to programming, it is
best to practice thinking recursively
8Recursive Definition LIST
- Consider the following list of numbers
- 24, 88, 40, 37
- Such a list can be defined as
- A LIST is a number
- or a number comma 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
9Recursive Definitions
- The recursive part of the LIST definition is used
several times, terminating with the non-recursive
part - number comma LIST
- 24 , 88, 40, 37
- number comma LIST
- 88 , 40, 37
- number comma LIST
- 40 , 37
- number
- 37
10Recursive Definitions Factorial
- N!, for any positive integer N, is defined to be
the product of all integers between 1 and N
inclusive - This definition can be expressed recursively as
- 1! 1
- N! N (N-1)!
- The concept of the factorial is defined in terms
of another factorial
11Recursive Definitions
12Outline
- Admin. and review
- Recursive thinking defining concept recursively
- Recursive method calls
- Places of recursion matter
13Traditional Method Calls
- Flow of control flows from one method to another
and returns as specified
foo
bar
main
bar()
foo()
14Recursive Method Calls
- What if a method calls itself?
void LotsOfPrints() System.out.println(i
nside LotsOfPrints) LotsOfPrints()
15Termination
- So we have another way to write infinite loops!
- To terminate, we have to stop making recursive
calls - Use conditionals to determine termination
void LotsOfPrints() if
(some-condition) do
non-recursive computation else
System.out.println(inside
LotsOfPrints) LotsOfPrints()
16Infinite Recursion
- All recursive definitions have to have a
non-recursive part - If they didn't, there would be no way to
terminate the recursive path - Such a definition would cause infinite recursion
- This problem is similar to an infinite loop, but
the non-terminating "loop" is part of the
definition itself - The non-recursive part is often called the base
case
17Termination (contd.)
- Introduce an input variable
- Value of input variable determines termination
void LotsOfPrints(int num) if (num 0)
System.out.println(the
bug stops here!) else
System.out.println(inside LotsOfPrints)
LotsOfPrints(num - 1)
18Control Flow
LotsOfPrints(2)
LotsOfPrints(1)
LotsOfPrints(0)
LotsOfPrints(1)
LotsOfPrints(0)
19Place of Recursion Ordering
void LotsOfPrints(int num) if (num
0) else
System.out.println(num)
LotsOfPrints(num - 1)
LotsOfPrints(5) 5 4
3 2 1
20Place of Recursion Ordering
void LotsOfPrints(int num) if (num
0) else
LotsOfPrints(num - 1)
System.out.println(num)
LotsOfPrints(5) 1 2
3 4 5
21Local and Formal Variables
- Each invocation of a method has its own set of
method variables formal parameters and local
variables
void LotsOfPrints(int num) int local
2num if (num 0)
else
LotsOfPrints(num - 1)
System.out.println(local)
LotsOfPrints(3) 2 4
6
22Control Flow
LotsOfPrints(2)
LotsOfPrints(1)
LotsOfPrints(0)
print(local)
print(local)
print(local)
23Exercise 1
- Without using any loop statement, write a sum
method that calculates the sum of the numbers
from 0 to n, where parameter n is a non-negative
integer?
24Exercise 2
- Without using any loop statement, write method
power(int x, int y) that raises integer x to the
power of y, where y is a non-negative integer? - Examples
- power(2, 1) 2
- power(2, 2) 4
- power(2, 10) 1024
25CS 112 Introduction to Programming
- Lecture 30
- Recursive Programming
- Richard Yang
26Outline
- Review and admin.
- Palindrome
- Change maker
- Towers of Hanoi
27Review What is Recursion?
- Follows the mathematical notion of induction
- There is a base case
- Inductive step provides solution for a larger
problem - solve a smaller problem
- extend it a bit
- LotsOfPrints(0) do nothing
- LotsOfPrints(n) LotsOfPrints(n-1), Print
28Recursive Programming
- A method in Java can invoke itself if set up
that way, it is called a recursive method - Each call to the method sets up a new execution
environment, with new parameters and local
variables - As always, when the method completes, control
returns to the method that invoked it (which may
be an earlier invocation of itself) - The code of a recursive method must include two
cases - the base case
- the recursive case
29Recursive Sum
int sum(int n) if (n 0) //
base case return 0 else
// recursive case return
sum(n-1) n
sum(4)
sum(0)
4
0
10
0
30Local and Formal Variables
- Each invocation of a method has its own set of
method variables formal parameters and local
variables
void LotsOfPrints(int num) int local
2num if (num 0)
else
LotsOfPrints(num - 1)
System.out.println(local)
LotsOfPrints(3) 2 4
6
31Control Flow
LotsOfPrints(2)
LotsOfPrints(1)
LotsOfPrints(0)
print(local)
print(local)
print(local)
32Recursive Exponentiation
int power(int x, int n) if (n 0)
// base case return 1
else // recursive case
temp power(x, n/2)
temp temp if (n 2 1)
temp x return temp
33Writing Recursive Programs
- Determine the structure of your method
- Think of the sub-problems that you may want to
solve, then make the definition of your method
general enough to handle them so that you can use
recursion - Determine the recursive case
- Determine the base case
34Outline
- Review and admin.
- Palindrome
- Change maker
- Towers of Hanoi
35Palindrome Problem
- A palindrome is a string that reads the same
backward or forward - Question how do you check a String to see
whether or not it is a Palindrome? - What is the signature of the method to allow
recursion? - What is the base case?
- What is the recursive case?
x
y
z
a
z
y
x
36Palindrome
- checkPalindrome(string, left, right)
- Base case
- if right lt left, then true
- if string.charAt(left) ! string.charAt(right),
then false - Recursive case
- check palindrome (string, left 1, right - 1)
37Palindrome Check
boolean checkPalindrome(String s, int left, int
right) if (right lt left) // base
return true else if (s.charAt(left) !
s.charAt(right)) // base return
false else return checkPalindrome(s,
left 1, right - 1)
38Outline
- Review and admin.
- Palindrome
- Change maker
- Towers of Hanoi
39Change Maker
- Recursion is useful for trying all possibilities
- Consider the change making problem
- Count number of ways to make change for a given
amount with pennies, nickels, dimes, quarters - Questions
- What is the signature of the method to allow
recursion? - What is the base case?
- What is the recursive case?
40Change Maker Structure
- Order coin types in increasing order and number
them - count(amount, num_types)
- number of ways to make amount cents using
num_types coins where num_types could be 0, 1,
2, 3, 4
41Change Maker Recursive Case
- Question count(11, 2) ?
- count(11, 2) sum of
- count(6, 2)
- count(11, 1)
- Two paths
- Use one more coin of the highest denomination,
reduce amount and try to make change for
remaining money - Or, discard the highest denomination and try to
make money with remaining denominations
42Change Maker Recursive Case
3
11, 2
2
1
1
1
1
0
43Change Maker Recursive Case
4
15, 2
3
1
2
1
1
1
44Change Maker Base Case
- amount lt 0 num_types 0 0
- amount 0 num_types 1 1
45Change Maker Code
int coins 1, 5, 10, 25 int count(int
amount, int num_types) if (amount lt 0
num_types 0) return 0 else if
(amount 0 num_types 1) return
1 else return count(amount -
coinsnum_types - 1, num_types)
count(amount, num_types - 1)
46Outline
- Review and admin.
- Palindrome
- Change maker
- Towers of Hanoi
47Towers of Hanoi
- The Towers of Hanoi is a puzzle made up of three
vertical pegs and several disks that slide on
the pegs - The disks are of varying size, initially placed
on one peg with the largest disk on the bottom
with increasingly smaller ones on top - The goal is to move all of the disks from peg 1
to peg 3 under the following rules - We can move only one disk at a time
- We cannot move a larger disk on top of a smaller
one
48Tower of Hanoi code
void moveTower (int numDisks, int start, int end,
int temp) if (numDisks 1)
System.out.println(move disk from start
to end) else
moveTower (numDisks-1, start, temp, end)
System.out.println(move disk from start
to end) moveTower (numDisks-1,
temp, end, start) public static void
main(String args) moveTower(4, 1, 3,
2)
49Towers of Hanoi
- An iterative solution to the Towers of Hanoi is
quite complex - A recursive solution is much shorter and more
elegant - See SolveTowers.java
- See TowersOfHanoi.java
50CS 112 Introduction to Programming
- Lecture 31
- Recursive Programming
- Richard Yang
51Outline
- Admin. and review
- Examples
52Admin.
- Assignment 8
- Recursive programming
- Assignment 9
- Enhance a web browser
- Replace your lowest assignment
- Date of second exam?
53Writing Recursive Programs
- Determine the structure of your method
- Think of the sub-problems that you may want to
solve, then make the definition of your method
general enough to handle them so that you can use
recursion - Determine the recursive case
- Determine the base case
54Examples
- int sum(int n)
- int power(int x, int n)
55Palindrome Check
boolean checkPalindrome(String s, int left, int
right) if (right lt left) // base
return true else if (s.charAt(left) !
s.charAt(right)) // base return
false else return checkPalindrome(s,
left 1, right - 1)
void main(String args) String str
xyzazyx boolean result
checkPalindrome(str, 0, str.length())
56Change Maker
int coins 1, 5, 10, 25 int count(int
amount, int nCoins) if (amount lt 0
nCoins 0) // base return 0 else
if (amount 0 nCoins 1) // base
return 1 else return
count(amount - coinsnCoins - 1, nCoins) //
use the largest coin
count(amount, nCoins - 1) // not use
void main(String args) int n count (99,
coins.length)
57Exercise Find Maximum
- Find the maximum of an array of numbers
- int findMax(int array)
- Questions
- What is the structure?
- What is the base case?
- What is the recursive case?
58Recursive findMax
int findMax(int items, int numElems) if
(numElems 1) return items0
int partResult findMax(items, numElems - 1)
if (partResult lt itemsnumElems - 1)
return itemsnumElems - 1 else
return partResult public static void
main(String args) int items 2,
4, 8, 7, 5, 9, 21, 11 int max
findMax(items, items.length)
59Binary Search
- Searching for a number in a sorted array (say 7)
- void search(int items, int targetElem)
- Linear scan would work, but could do better
- Check in the middle and decide which half to
search in - Questions
- What is the structure of the method?
- What is the base case?
- What is the recursive case?
60Binary Search Structure and Base
- boolean find(items, targElem, rangeBeg, rangeEnd)
- - items is an array of values
- - targElem is element we are searching for
- - rangeBeg is beginning of current array section
- - rangeEnd is end of current array section 1
- Base case array section is size one
- return true if targElem is contained in the
single entry remaining - return false if targElem is not contained in that
entry - initiate recursion find(items, targElem, 0,
items.length)
61Binary Search Recursive Case
static boolean find(int array, int elem, int
rangeBeg, int rangeEnd) if (rangeBeg
rangeEnd - 1) // base return
(arrayrangeBeg elem) int mid
(rangeBeg rangeEnd)/2 if (arraymid
elem) // base return true else
if (elem lt arraymid) return find(array,
elem, rangeBeg, mid) else return
find(array, elem, mid 1, rangeEnd)
62Exercise Tiled Pictures
- Questions
- What is the structure of the draw method
- What is the recursive case?
- What is the base case?
- See TiledPictures.java
63Exercise Fractals
- A fractal is a geometric shape made up of the
same pattern repeated in different sizes and
orientations - The Koch Snowflake is a particular fractal that
begins with an equilateral triangle - To get a higher order of the fractal, the sides
of the triangle are replaced with angled line
segments - See KochSnowflake.java
- See KochPanel.java
64Towers of Hanoi
- The Towers of Hanoi is a puzzle made up of three
vertical pegs and several disks that slide on
the pegs - The disks are of varying size, initially placed
on one peg with the largest disk on the bottom
with increasingly smaller ones on top - The goal is to move all of the disks from peg 1
to peg 3 under the following rules - Move only one disk at a time
- Cannot move a larger disk on top of a smaller one
65move(3 1 -gt 3 2)
move(2 1 -gt 2 3)
Disk 3 1 -gt 3
move(2 2 -gt 3 1)
66Tower of Hanoi code
void moveTower (int numDisks, int start, int end,
int temp) if (numDisks 1)
System.out.println(move disk from start
to end) else
moveTower (numDisks-1, start, temp, end)
System.out.println(move disk from start
to end) moveTower (numDisks-1,
temp, end, start) public static void
main(String args) moveTower(4, 1, 3,
2)
67Towers of Hanoi
- An iterative solution to the Towers of Hanoi is
quite complex - A recursive solution is much shorter and more
elegant - See SolveTowers.java
- See TowersOfHanoi.java
68CS 112 Introduction to Programming
- Lecture 32
- Recursive Programming
- Richard Yang
69Outline
- Admin. and review
- Recursive search
- Indirect recursion
- Recursion vs. iteration
70Admin.
- Assignment 8
- Recursive programming
- Assignment 9
- Enhance a web browser
- Replace your lowest assignment
- Second exam 7 to 9pm on Dec. 6
71Writing Recursive Programs
- Determine the structure of your method
- Think of the sub-problems that you may want to
solve, then make the definition of your method
general enough to handle them so that you can use
recursion - Determine the recursive case
- Determine the base case
72move(3 1 -gt 3 2)
move(2 1 -gt 2 3)
Disk 3 1 -gt 3
move(2 2 -gt 3 1)
73Tower of Hanoi Code
void moveTower (int numDisks, int start, int end,
int temp) if (numDisks 1)
System.out.println(move disk from start
to end) else
moveTower (numDisks-1, start, temp, end)
System.out.println(move disk from start
to end) moveTower (numDisks-1,
temp, end, start) public static void
main(String args) moveTower(4, 1, 3,
2)
74Summary of Examples
- int sum(int n)
- int power(int x, int n)
- int findMax(int items, int numElems)
- boolean checkPalindrome(String s,
int left, int right) - int count(int amount, int nCoins)
- boolean find(int items, int targElem,
int rangeBeg, int rangeEnd) - - void moveTower (int numDisks,
int start, int end, int temp)
75Outline
- Admin. and review
- Recursive search
- Indirect recursion
- Recursion vs. iteration
76Search
- Often we need to search for a solution among a
large number of possibilities, e.g., - When playing Chess, we want to check what the
best next step is - We can use recursion to search the space
- One major issue is that we do not fall into
infinite loop - In the previous examples, we always go from a
larger problem to a smaller problem, therefore no
such possibility - We may need to remember history
- We may need to revise history so that we will
search the whole space - We study two examples
- Search for a route in a Maze
- The Knights tour
- Your homework will consider anther one
- Eight queens
77Maze
- Notation
- 1 allowed
- 0 blocked
- Objective search a path through a maze?
- Questions
- What is the structure
- What is the recursive case
- What is the base case
1
0
1
1
1
0
0
1
1
1
1
1
0
1
1
1
78Maze Trace
1
0
1
1
1
0
0
1
1
1
1
1
0
1
1
1
79Maze Dead End
1
0
1
1
1
0
0
1
1
1
1
1
0
1
1
1
1
4
2
3
80Maze Keep State
1
0
1
1
1
0
0
1
1
1
1
1
0
1
1
1
1
4
2
3
81Maze Traversal
- From each location, we use recursion to search in
each direction - Recursion keeps track of the path through the
maze - To avoid returning to a place that has already
been visited, mark any place that has already
been visited - Otherwise, may have infinite loop
- Lesson to avoid infinite loop, recursion may
need to keep track of state - The base cases
- Reaching the final destination
- An invalid move
- See MazeSearch.java
- See Maze.java
82Knight's Tour Problem
- Knight's Tour Problem On an n x n Chess Board,
starting from a square, can a knight visit all
the squares in exactly n2-1 moves
83Knights Tour
- Questions
- What is the structure
- What is the recursive case
- What is the base case
84Knights Tour
- From each location, we use recursion to search in
each possible new position - Recursion keeps track of the path through the
board - To avoid returning to a location that has already
been visited, mark any location that has already
been visited - If a search from a location is not successful,
unmark the previous mark at that location! - The base case
- The whole board is visited!
- See KnightMain.java
- See ChessBoard.java
85Outline
- Admin. and review
- Backtrack and search
- Indirect recursion
- Recursion vs. iteration
86Indirect Recursion
- A method invoking itself is considered to be
direct recursion - A method could invoke another method, which
invokes another, etc., until eventually the
original method is invoked again - For example, method m1 could invoke m2, which
invokes m3, which in turn invokes m1 again - This is called indirect recursion, and requires
all the same care as direct recursion - It is often more difficult to trace and debug
87Indirect Recursion
88Outline
- Admin. and review
- Backtrack and search
- Indirect recursion
- Recursion vs. iteration
89Recursion vs. Iteration
- For some problems, recursion provides an elegant
solution, often cleaner than an iterative version - However, iterative solutions are generally faster
- Note that just because we can use recursion to
solve a problem, doesn't mean we should - For instance, we usually would not use recursion
to solve the sum of 1 to N problem, because the
iterative version is easier to understand - You must carefully decide whether recursion is
the correct technique for any problem
90Recursive Fibonacci
- Fibonacci sequence 1, 1, 2, 3, 5, 8, 13, 21
- A fibonacci number is sum of previous two numbers
- Fibonacci(1) 1
- Fibonacci(2) 1
- Fibonacci(n) Fibonacci(n-1) Fibonacci(n-2)
int Fibonacci(int n) if (n 1 n
2) return 1 else
return Fibonacci(n-1) Fibonacci(n-2)
91Iterative Fibonacci
int Fibonacci(int n) if (n1 n2)
return 1 int prev_fib 1
int curr_fib 1 for (int count3 count
lt n count) temp
curr_fib prev_fib prev_fib
curr_fib curr_fib temp
return curr_fib
92Backup Slides
93Recursive Sorting
- Goal sort a jumbled set of numbers
- recursively sort all but one element
- Insert last item at the right place
94Sort Code
void sort(int items) if (items.length
1) return int
newItems allButLast(items)
sort(newItems) insert(newItems,
itemsitems.length - 1, items)
95Sort Code allButLast
int allButLast(int items) int
result new int items.length - 1 for
(int j 0 jltitems.length - 1 j)
resultj itemsj return result
96Sort Code insert
void insert(int partResult, int value, int
result) int j for (j0
jltpartResult.length
partResultj lt value j)
resultj partResultj resultj
value for ( j lt partResult.length
j) resultj1 partResultj
97Recursive Merge-Sorting
- Sort a jumbled set of numbers
- Break into two halves, recursively sort
- Merge
98Recursive Sorting Merge
- Merge(a1,a2,an b1,b2,bn)
- if a1 lt b1 result a1, Merge(a2an
b1,b2,bn) - if b1 lt a1 result b1,
Merge(a1,a2an b2bn) - Merge(nothing, b1,b2,bn) b1, b2,bn
- Merge(aArray, apos, bArray, bpos, resArray,
resPos) - if aArrayapos lt bArraybpos then
- resArrayresPos aArrayapos
- Merge(aArray, apos 1, bArray, bpos, resArray,
resPos 1) - if aArrayapos gt bArraybpos then
- resArrayresPos bArraybpos
- Merge(aArray, apos , bArray, bpos 1, resArray,
resPos 1)
99Recursive Sort code
void Sort(int items) // base case
could have considered a base case of 1 if
(items.length 2) if (items0 gt
items1) int temp
items1 items1 items0
items0 temp
return
100Sort (contd.)
// recursive case int half1
FirstHalf(items) int half2
SecondHalf(items) Sort(half1)
Sort(half2) Merge(half1, 0, half2, 0,
items, 0)
101Recursive Merge
void Merge(int a, int aPos, int b,int bPos,
int res, int resPos) if (aPos
a.length bPos b.length)
return if (aPos a.length)
for (int jbPos, k resPos jltb.length j,
k) resk bj if
(bPos b.length) for (int jaPos, k
resPos jlta.length j, k)
resk aj
102Merge (contd.)
if (aaPos lt bbPos)
resresPos aaPos
Merge(a, aPos 1, b, bPos, res, resPos 1)
else resresPos
bbPos Merge(a, aPos, b, bPos
1, res, resPos 1)
103Helper Methods
int FirstHalf(int items) int
result new int items.length/2 for
(int j0 jltresult.length j)
resultj itemsj return result
int SecondHalf(int items) int
result new int items.length -
items.length/2 for (int j0, k
items.length/2 jltresult.length j, k)
resultj itemsk return
result