Title: Professor: Munehiro Fukuda
1CSS342 Recursion
- Professor Munehiro Fukuda
2Topics
- Day 1 Lecture
- Basic recursions
- Sum
- Fact
- Print a number in any base
- Binary search
- Fibonacci sequence
- Tracing recursions
- Recursive applications
- Towers of Hanoi
- Divide Conquer (Calculating the space of a
given polynomial) - Backtrack (8 queens)
- Efficiency of recursion
- Day 2 Lab Work
- Drawing Fractal Figures with Recursion
- Ruler
- Koch Curves
- Sierpinski Arrowhead
- Gosper or Hilbert Curves
3Basic Recursions
Basic Recursions
- Break a problem into smaller identical problems
- Each recursive call solves an identical but
smaller problem. - Stop the break-down process at a special case
whose solution is obvious, (termed a base case) - Each recursive call tests the base case to
eventually stop. - Otherwise, we fall into an infinite recursion.
4Example 1 The Sum of the First NPositive
Integers
Basic Recursions
- Definition
- sum(n) n (n-1) (n-2) 1 for any
integer n gt 0 - Recursive relation
- sum(n) n (n-1) (n-2) 1
- n sum(n-1)
- Looks so nice, but how about n 1?
- sum(1) 1 sum(0), but the argument to sum( )
must be positive - Final recursive definition
- sum(n) 1 if n 1 (Base case)
- n sum(n-1) if n gt 1 (Recursive call)
5Recursive Definition of sum(n)
Basic Recursions
int sum(int n) if (n 1) // base case
return 1 else return n sum(n-1) //
recursive call A How should I test this
functions correctness? Use the box method A
box has each functions local environment ex.
cout ltlt sum(3)
1. Arguments 2. Local variables 3. Place holder
for the value returned by a called
function 4. A return value
n 3 A sum(n-1) ? return ?
6Box trace of sum(3)
Basic Recursions
cout ltlt sum(3)
n 3 A sum(n-1)? return ?
n 3 A sum(n-1) ? return ?
n 2 A sum(n-1)? return ?
n 1 return 1
Each box corresponds to a functions activation
record or stack.
7Example 2 The Factorial of n
Basic Recursions
- Definition
- factorial(n) n (n-1) (n-2) 1 for any
integer n gt 0 - factorial(0) 1
- Recursive relation
- factorial(n) n (n-1) (n-2) 1
- n factorial(n-1)
- Looks so nice, but how about n 1?
- factorial(1) 1 factorial(0) but the argument
to factorial( ) must be positive - Final recursive definition
- factorial(n) 1 if n 1
- n factorial(n-1) if n gt 1
8Recursive Definition of facotrial(n)
Basic Recursions
int fact(int n) if (n 1) // base case
return 1 else return n
fact(n-1) // recursive call A Trace its
execution using the box method ex. cout ltlt
fact(3)
n 3 A fact(n-1) ? return ?
9Box trace of fact(3)
Basic Recursions
cout ltlt fact(3)
n 3 A fact(n-1)? return ?
n 3 A fact(n-1) ? return ?
n 2 A fact(n-1)? return ?
n 1 return 1
10Precondition of fact(n)
Basic Recursions
- Precondition n gt 1
- If the precondition is violated, what happen?
- Fact(0) calls fact(-1), which calls fact(-2), .
- For robustness, given a negative number or 0,
fact should stop a recursive call.
Always correct to recursions
int fact(int n) if (n lt 1) // base case
for n 1 or bad args. return 1 else
return n fact(n-1) // recursive call A
11Example 3 Printing Numbers in Any Base
Basic Recursions
How to convert a decimal to a hexadecimal Dividend
Remainder 16) 1234567890(10).. 16)
7716049(10)6 16) 482253(10)1 16)
30140(10)13(D) 16)
1883(10)12(C) 16)
117(10)11(B) 16)
7(10)....5 16) 0(10)....7
2. Print each reminder from the
bottom 75BCD16(16)
1. Divide by a base(16)
12Recursive Definition of printNum(n,base)
Basic Recursions
void printNum(int n, int base) static string
DIGIT_TABLE 0123456789abcdef if (n gt
base) // recursive call A printNum( n /
base, base ) // else n lt base base case
cout ltlt DIGIT_TALBE n base Trace its
execution using the box method ex. cout ltlt
print(123456789, 16)
n 123456789, base 16 A fact(n-1) returns
nothing Print n base ? return nothing
13Box trace of printNum(123456789, 16)
Basic Recursions
Trace by yourself (This type of tracing problems
will be given in your mid term.)
14Example 4 Binary Search
Basic Recursions
An entire sorted list
First half
Second half
First half
Second half
First half
- The search divides a list into two small
sub-lists till a sub-list is no more divisible. - Each step needs the top/tail indexes and a target
item.
Can we call binarySearch( ) recursively?
15Binary Search (Recursive Version)
Basic Recursions
int binarySearch( const int array, int top, int
tail, int target ) int mid (top
tail)/2 if ( target arraymid ) return
mid else if ( target lt arraymid ) return
binarySearch( array, top, mid-1, target ) else
if ( target gt arraymid ) return binarySearch(
array, mid1, tail, target )
Question if it does not find the target, how
can we stop this program?
16Binary Search Revisited
Basic Recursions
i
i1
35
47
top
tail
mid (top tail)/2 (i i1)/2 i top mid
1 i 1
In the next recursive call, top i 1 tail
i thus top gt tail!! Base cases (1) if (target
arraymid) return mid (2) if top gt tail
return 1
17Binary Search (Correct Recursive Version)
Basic Recursions
int binarySearch( const int array, int top, int
tail, int target ) int mid (top
tail)/2 if ( target arraymid ) return
mid // find it else if ( top gt tail ) return
-1 // cannot find it else if ( target lt
arraymid ) return binarySearch( array, top,
mid-1, target ) else if ( target gt arraymid
) return binarySearch( array, mid1, tail,
target )
18Example 5 Multiplying Mice
Basic Recursions
Month 1
- Quite difficult to keep track of the
- population explosion.
Month 2
Month 3
Month 4
Month 5
Month 6
Babies
Month 7
Recursive relation babies in Month 7 mice in
Month 5 adults in Month 7 mice in Month 6
19The Fibonacci Sequence
Basic Recursions
- mice(n) mice(n-1) mice(n-2)
- Then, what are base cases?
- Recursive definition
mice(1) mice(0) mice(-1) cant happen. Thus,
mice(1) 1 mice(2) mice(1) mice(0) cant
happen, either. Thus, mice(2) 1
mice(n) 1 if n 1 or 2 mice(n-1)
mice(n-2) if n gt 2
20Tracing mice(n)
Basic Recursions
m(6) Return m(5)m(4)
8
3
5
2
1
2
3
1
1
2
1
1
1
1
1
21Recursive Applications
Recursive Applications
- Discrete Mathematics (Combinatorics, Puzzles,
Coding Theory) - Tower of Hanoi and Gray Code
- Divide and Conquer
- Mergesort, Convex Hall, and Fast Fourier
Transform - Backtrack
- 8 Queens, Maze and Classic Chess Program
- Fractal Figures
- Koch, Sierpinski Allowhead, Gosper, Hilbert, and
Dragon curves
22Towers of Hanoi
Recursive Applications
A
B
C
Find how to move dishes from A to B using
C. Restrictions
23Solution
Recursive Applications
move(n, A, B, C)
In order to move n dishes from A to B via C,
if we could move n-1 dishes from A to C via B,
move(n-1, A, C, B)
we could move a dish, (i.e., the last one) from A
to B (via C),
move(1, A, B, C)
and thereafter, we would move n-1 Dishes from C
to B via A!
move(n-1, C, B, A)
24Example Code
include ltiostreamgt include ltstdlib.hgt using
namespace std void move( int n, char orig, char
dest, char temp ) if ( n 1 ) cout ltlt
"move disk 1 from " ltlt orig ltlt " to " ltlt dest ltlt
endl else move( n - 1, orig, temp, dest
) cout ltlt "move disk " ltlt n ltlt " from " ltlt
orig ltlt " to " ltlt dest ltlt endl move( n - 1,
temp, dest, orig ) int main( int argc,
char argv ) int nDishes atoi( argv1
) move( nDishes, 'A', 'B', 'C' ) cout ltlt
"completed" ltlt endl return 0
25Tracing move(n, A, B, C)
Recursive Applications
move(3, A, B, C)
4
move(2, A, C, B)
move(1, A, B, C)
move(2, C, B, A)
Locally, A is A, C is B, B is C.
Locally C is A, B is B, A is C.
1
5
move(1, C, A, B)
move(1, A, B, C)
2
6
move(1, C, B, A)
move(1, A, C, B)
7
3
move(1, A, B, C)
move(1, B, C, A)
26Divide-and-Conquer AlgorithmsComputational
Geometry Finding a Convex Hall
Recursive Applications
- Divide
- Divide a problem into two sub-problems
recursively so that the sub-problems are
calculated by themselves. - Conquer
- Form a new solution from the solutions answered
by the sub-problems
The convex hull problem Trivial algorithm
O(n2) Divide conquer O(nlogn)
27BacktrackTrace every combination until
encountering a solution
Recursive Applications
- The eight queens problem
- Place 8 queens on a 8 8 chessboard so that no
queen can attack any other queen. - Place a queen from the column 0 to 7 as checking
if the queens placed on the former columns can
attack the current queen.
28BacktrackThe Eight Queen Problem
Recursive Applications
Q ??
for ( int col 0 col lt 7 col ) for (
int row 0 row lt 7 row ) if (
safeLocation( table, row, col ) )
tablerowcol true break
// oops! No safe row to place a new queen
// I got to go back to the previous column!
Q
Q
Q
Q
Q
- Then, how can I go back to the previous column?
Just col--?
29BacktrackThe Eight Queen Problem
Recursive Applications
0,0 -gt 0,1 NO 1,1 NO
2,1 -gt 0,2 NO 1,2 NO
2,2 NO 3,2 NO
4,2 -gt 0,3 NO
1,3 -gt 0,4 NO
1,4 NO
2,4 NO
3,4 -gt 0,5 NO
1,5 NO
2,5 NO
3,5 NO
4,5 NO
5,5 NO
6,5 NO
7,5
NO 4,4 NO
5,4 NO
6,4 NO
7,4 -gt 0,5
Q ??
Q
Q
Q
Q
Q
30BacktrackThe Eight Queen Problem
Recursive Applications
bool addQueen( bool tSIZESIZE, int col )
if ( col gt SIZE ) return true
// all cols have been examined for (
int row 0 row lt SIZE row ) if (
safeLocation( t, row, col ) ) // this row may
be a candidate trowcol true
// place a new queen if ( addQueen(
t, col 1 ) ) return true
// all the following cols were filled
else trowcol false // A wrong
position. Try the next row return
false // all rows
examined, but no candidates int main( )
bool tableSIZESIZE // there
are no matrix templates in STL init( table )
// all tableij
false if ( addQueen( table, 0 ) ) print(
table ) else cout ltlt "no solution" ltlt
endl
31Fractal CurvesDrawing a Ruler
Recursive Applications
// java code to draw a ruler void drawRuler(
Graphics g, int left, int right, int level )
if ( level lt 1 ) return int mid (
left right ) / 2 g.drawLine( mid, 80, mid,
80 level 5 ) drawRuler( g, left, mid
1, level 1 ) drawRuler( g, mid 1, right,
level 1 )
mid at level 1
mid at level 1
mid at level 1
mid at level 1
Initial right
Initial left
mid at level 2
mid at level 2
mid at level 3
32Fractal CurvesDrawing a Koch Curve using a Turtle
Recursive Applications
class Turtle public Turtle( float
initX0.0, float initY0.0, float initAngle0.0 )
Turtle( ) void draw( float d ) // draw
a line from the current position for distance d
void move( float d ) // simply move from the
current position for distance d void turn(
float a ) // turn left by angle a private
float angle // presented in degree but not in
radian oftream out int main( )
Turtle t t.draw( 10 ) t.turn( 45 )
t.move( 10 ) t.draw( 10 )
33Fractal CurvesDrawing a Koch Curve using a Turtle
Recursive Applications
class Koch Turtle public Koch( float
initX0.0, float initY0.0, float initAngle0.0)
Turtle( initX, initY, initAngle ) )
Koch( ) curve( int level, float length )
if ( level gt 1 ) curve( level 1,
length ) turn( 60 ) curve(
level 1, length ) turn( -120 )
curve( level 1, length ) turn( 60
) curve( level 1, length )
draw( length ) int main( )
Koch k(100, 100, 0) k.curve( 3, 10 )
Draw the level-3 Koch curve here
34Recursion and Efficiency
Efficiency
- Programmability
- Capable of breaking down a complex problem
- Based on mathematical induction
- Efficiency
- The overhead associated with function calls
- (Bookkeeping the current stack and creating a new
one) - The inherent inefficiency of some algorithm
- (Repeating the same computation)
35Efficiency of mice(n)
Efficiency
O(2n)
m(6) Return m(5)m(4)
36Iterative Solution of mice(n)
Efficiency
int iterativeMice(int n) int previous
1 int current 1 int next 1 for (int i
3 i lt n i) next current
previous previous current current
next return next
Efficiency of mice(n) O(n-2)O(n)
37Recursion versus Iteration
Efficiency
Problems Recursion Iteration Fibonacci
sequence O(2n) O(n) Sum/Fact/printNum O(n)
O(n) function call overhead Binary
search O(log n) O(log n) Tower of
Hanoi O(2n) Fractal figures (Koch) O(4n) Can
you program it? N queens O(Nn)
- Discover a recursive solution if it is easier.
- Convert it to iteration if an iterative solution
is more efficient. - When a recursion incurs more iterations
- When each iteration includes a few computation