Title: Recursion
1Recursion
- just in case you didnt love loops enough
2Recursion
- A recursive method is a method that contains a
call to itself - Often used as an alternative to iteration when
iteration is awkward or inelegant - Each recursive call is given a smaller portion of
the original problem - Last recursive call solves diminished problem
without recursion
3Example
- // method writes digits of a non-negative number,
stacked vertically - public void write_vertical(int n)
-
- n Math.abs(n)
- if (n lt 10)
- System.out.println( n)
- else
-
- write_vertical(n / 10)
- System.out.println( n 10)
-
4Tracing recursive method write_vertical
Output
1. write_vertical(52406) n52406
n/105240
5
10. System.out.println ( n10)
2
2. write_vertical(n/10) n5240
n/10524
9. System.out.println(n10)
4
3. write_vertical(n/10) n524
n/1052
0
8. System.out.println ( n10)
6
4. write_vertical(n/10) n52
n/105
7. System.out.println ( n10)
5. write_vertical(n/10) n5
Stop recursion!
6. System.out.println( n)
5Elements of recursive method
- Base case problem is simplified to the point
where recursion becomes unnecessary n lt 10 - Variant expression the part of the problem that
changes, making the problem smaller n - Recursive call method calls itself
write_vertical (n / 10)
6How recursion works
- Activation record memory block that stores all
the information a method needs to work - values of local variables parameters
- where method should return to (so calling method
can resume execution)
7How recursion works
- When a method call is encountered, execution of
current method ceases - Information for newly called method is stored in
an activation record - Method executes
8How recursion works
- If new method contains another method call, the
process just described repeats - Each recursive call generates its own activation
record - as each recursive call is encountered, previous
activation record is stored on run-time stack - when last call fails to generate a new activation
record, stacked calls are removed (in reverse of
the order they were stored), and each process
continues in succession
9Remember, for a recursive method to be successful
...
- Must be a problem with one or more cases in which
some subtasks are simpler versions of the
original problem - use recursion for these - Must also have one or more cases in which entire
computation is accomplished without recursion
(base case)
10Another example the powers method
- Suppose you wanted to find the value of Xn
- For most values of n, we can solve this
iteratively using a simple loop - int answer 1
- for (int c 1 c lt n c)
- answer X
- We can take care of the cases of n1 or n0 with
simple if statements but what about a negative
value of n?
11Finding a recursive solution
- We can observe that for any value of n, Xn is
equal to X X(n-1) - Armed with this information, we can easily
develop a recursive solution that covers all
values of X and n
12Recursive power method
- double rpower (double X, int n)
-
- if (X 0)
- return 0
- else if (n 0)
- return 1
- else if (n gt 0)
- return X rpower(X, n-1)
- else // n lt 0
- return 1 / rpower(X, -n)
13 A classic the Towers of Hanoi
- Initial situation a stack of donut-shaped disks
stacked in in order of decreasing size from
bottom to top on a wooden peg - Object move all the disks to a second peg, one
at a time - third peg available as temporary holding area
- at no time may a larger disk be placed on top of
a smaller disk
14Solving towers of Hanoi
- Simplest case tower of one disk -- move disk to
destination peg - With stack of two disks
- Move top disk to third peg
- Move next disk to destination
- Move disk from third peg to destination
15Solving towers of Hanoi
- Simplest case tower of one disk -- move disk to
destination peg - With stack of two disks
- Move top disk to third peg
- Move next disk to destination
- Move disk from third peg to destination
16Solving towers of Hanoi
- Simplest case tower of one disk -- move disk to
destination peg - With stack of two disks
- Move top disk to third peg
- Move next disk to destination
- Move disk from third peg to destination
17Solving towers of Hanoi
- Simplest case tower of one disk -- move disk to
destination peg - With stack of two disks
- Move top disk to third peg
- Move next disk to destination
- Move disk from third peg to destination
18Solving towers of Hanoi
- Simplest case tower of one disk -- move disk to
destination peg - With stack of two disks
- Move top disk to third peg
- Move next disk to destination
- Move disk from third peg to destination
19Solving towers of Hanoi
- Stack of 3
- Move 2 disks from 1st peg to 3rd peg, using
method already described - Move 1 disk from 1st to 2nd
- Move 2 disks from 3rd to 2nd
20Solving towers of Hanoi
- When there are two or more disks to move, always
use third peg - With more than two disks, we can solve the
problem recursively by recognizing that the pegs
are interchangeable -- that is, any peg can be
used as source, destination, or spare
21Solving towers of Hanoi
- In general, for a stack of n disks
- Move n-1 disks from peg 1 to peg 3
- Move 1 disk from peg 1 to peg 2
- Move n-1 disks from peg 3 to peg 2
22Towers of Hanoi
- The top N-1 disks must be moved to peg 2,
allowing you to then move the largest disk from
peg 1 to peg 3. - You can then move the N-1 disks from peg 2 to peg
3. - Only two pegs are involved in a single move for
this, well employ a helper method, moveOne
23public void towersOfHanoi (int N, char from,
char to, char spare) if (N 1)
moveOne(from, to) else towersOfHanoi(N
-1, from, spare, to) moveOne (from,
to) towersOfHanoi(N-1, spare, to,
from) private void moveOne(int from, int
to) System.out.println(from ---gt to)
24Drawing pictures with recursion
- We used ASCII art to illustrate how iteration
worked we can do the same with recursion - For example, if we wanted to draw a line using
several instances of a single character, we could
write a loop like the one below - for (int x lineLen x gt 0 x--)
- System.out.print( )
- We can do the same task recursively see next
slide
25Example
public void drawLine (int x) if (x
0) return System.out.print() drawLine(x-1
)
26Same example, slightly different
- The original iterative line drawing routine was
different from typical examples weve seen in the
past, in that the counter was counting down
instead of up - I did this to illustrate how the iterative
version relates to the recursive version the
problem (value of counter) gets smaller with each
loop iteration, or each recursive call - The situation is the same if we have the counter
counting up, but its a little harder to see
27Example
Iterative version for (int x 0 x lt
someConstant x) System.out.print (
) Equivalent recursive version public drawLine
(int x, int someConstant) if (x lt
someConstant) System.out.print() drawLin
e (x1, someConstant) Instead of x getting
smaller, the distance between x and someConstant
gets smaller
28When Not to Use Recursion
- When recursive algorithms are designed
carelessly, it can lead to very inefficient and
unacceptable solutions - In general, use recursion if
- A recursive solution is natural and easy to
understand. - A recursive solution does not result in excessive
duplicate computation. - The equivalent iterative solution is too complex.
29Preventing infinite recursion
- One-level recursion every case is either a
stopping case or makes a recursive call to a
stopping case - Since most recursive functions are, or have the
potential to be, recursive beyond just one level,
need more general method for determining whether
or not recursion will stop
30Preventing infinite recursion
- Define a variant expression
- numeric quantity that decreases by a fixed amount
on each recursive call - in towers of Hanoi, variant expression was height
-- each recursive call used height -1 as
parameter - Base case is when variant expression is less than
or equal to its threshold value