Recursion

Java
Methods AB
TM
Maria Litvin
Gary Litvin
Data Structures
C H
T
A
P
T P
R
E
R — 4
Recursion
Copyright © 2003-2004 by Maria Litvin, Gary Litvin, and Skylight Publishing. All rights reserved.
Objectives:

Take a fresh look at recursion

Learn when to use recursion and when to
stay away from it

Learn to prove the correctness of
recursive methods

Get ready for the Game of Hex lab
4-2
Recursion Basics

A recursive method has a base case and a
recursive case
– In the base case, there are no recursive calls
– In the recursive case, the method calls itself, but for
a “smaller” task

Recursive calls must eventually converge to
the base case, when recursion stops
4-3
Example 1
ABCD
Take
substring
public String reverse (String s)
{
Base case
if (s.length() < 2)
(nothing to do)
return s;
A
Reverse
substring
A
return reverse (s.substring (1)) +
s.charAt(0);
}
Recursive case
BCD
DCB
Append the
first char
DCBA
4-4
Need x7
Example 2
7 / 2 == 3
public double pow (double x, int n)
{
if (n == 0)
Base case
return 1.0;
double y = pow (x, n / 2); Recursive
case
y *= y;
if ( n % 2 != 0 )
Caution: NOT
y *= x;
double y = pow(x, n / 2) *
return y;
}
First get
y = x3
Then square
y*y = x6
7 is odd, so
y *= x
pow(x, n / 2);
4-5
ArrayList fruits = new ArrayList ();
fruits.add ("apples");
fruits.add ("bananas");
Example 3
ArrayList snacks = new ArrayList ();
snacks.add ("chips");
snacks.add ("pretzels");
ArrayList food = new ArrayList ();
food.add ("Fruits");
food.add (fruits);
food.add ("Snacks");
food.add (snacks);
Recursive calls to
ArrayList’s toString
method take place
here
System.out.println(food);
Output:
[Fruits, [apples, bananas], Snacks, [chips, pretzels]]
4-6
When to Use Recursion

Recursion is especially useful for handling
nested structures and branching processes





 



 
 


4-7
1.

Example 4



public void traverse (TreeNode root)
{
if (root != null)
{
display (root.getValue( )); // 1
traverse (root.getLeft ( )); // 2
traverse (root.getRight ( )); // 3
}
}



 

 
 
2.









 
 
 
3.








 



 
 


4-8
Example 5
ABCD
DBCA
public void permutations
(StringBuffer str, int n)
{
if (n <= 1)
System.out.println (str);
else
Recursive case
{
for ( int i = 0; i < n; i++ )
{
swap (str, i, n-1);
permutations (str, n-1);
swap (str, n-1, i);
}
}
}
ABCD
ADCB
ABCD
ABDC
ABCD
ABCD
BCD A
CBD A
CDB A
DCB A
BDC A
DBC A
DCA B
CDA B
CAD B
ACD B
DAC B
ADC B
BDA C
DBA C
DAB C
ADB C
BAD C
ABD C
BCA D
CBA D
CAB D
ACB D
BAC D
ABC D
4-9
Use Recursion

When it simplifies code
Do Not Use Recursion

When a method allocates large local arrays

When a method unpredictably changes fields

When iterations work just as well
4-10
Just As Easy With Iterations
public String reverse (String s)
{
if (s.length( ) < 2)
return s;
public String reverse (String s)
{
String r = "";
for (int i = s.length( ) - 1;
i >= 0; i--)
r += s.charAt (i);
return r;
return reverse (s.substring(1))
+ s.charAt(0);
}
}
4-11
Not Easy Without Recursion
public void traverse (TreeNode root)
{
if (root != null)
{
display (root.getValue ( ));
traverse (root.getLeft ( ));
traverse (root.getRight ( ));
}
}
Need your own
stack to do this
without recursion!
Rule of thumb: use
recursion when the
process is branching, i.e.,
when the method is called
recursively more than once
or within a loop
4-12
Very Inefficient Recursive Code
public long fibonacci (int n)
{
if (n < 2)
return 1;
else
return fibonacci (n-2) +
fibonacci (n-1);
}
fibonacci(100) takes
50 years to run
public long fibonacci (int n)
{
long f1 = 1, f2 = 1, next;
while (n > 2)
{
next = f1 + f2;
f1 = f2;
f2 = next;
n--;
}
return f2;
}
fibonacci(100) takes
a few microseconds
to run
4-13
Recursion and Math Induction

Recursive methods are hard to trace in a
conventional way

A recursive method can be proven correct using
math induction

Other properties of a recursive method (running
time, required space, etc.) can be obtained by
using math induction
4-14
Math Induction Basics

You have a sequence of statements
P1, P2, P3, ... Pn-1 , Pn , ...

P1 is true (“base case”)

You can prove that for any n > 1, if P1, ... Pn-1
It is often
possible to
prove that if
Pn-1 is true
then Pn is
also true
are all true then Pn must be true, too

Then you can conclude (“by math induction”)
that Pn is true for any n  1
4-15
Example:
Prove that for any n  1
1 + 2 + 4 + ... + 2n = 2n+1 - 1
Proof:
1. If n = 1 then 1 + 2 = 22 - 1
2. Suppose (induction hypothesis)
1 + 2 + 4 + ... + 2n-1 = 2n - 1
Then
1 + 2 + 4 + ... + 2n =
(1 + 2 + 4 + ... 2n-1) + 2n = 2n - 1 + 2n =
2·2n - 1 = 2n+1 - 1
By math induction the equality is true for any n  1, q. e. d.
4-16
Math Induction and Recursion
public String reverse (String s)
{
if (s.length( ) < 2)
return s;
return reverse (s.substring(1))
+ s.charAt(0);
}
Let us prove that this method works, i.e., that
reverse(s) indeed returns the reverse of s. We
will use math induction “over the length of s.”
4-17
Proof
Let n = s.length();
public String reverse (String s)
{
if (s.length < 2)
return s;
return reverse (s.substring(1))
+ s.charAt(0);
1. If n = 0 or n = 1 then reverse
works because the string
}
remains unchanged
2. Suppose (induction hypothesis)
reverse works for any string of length
n-1. Then it works for s.substring(1).
So we reverse that substring and then
append the first char of s at the end.
We get the reverse of s.
By math induction, reverse works for
a string of any length, q. e. d.
4-18
Towers of Hanoi

Objective: move the tower from one peg to
another, moving one disk at a time and never
placing a larger disk on top of a smaller one

This puzzle was invented by François Edouard
Anatole Lukas and published in 1883
4-19
Towers of Hanoi Recursive Solution
For n disks:

If n = 1, just move the
disk to the desired peg

If n > 1
– move the top n-1 disks
to a spare peg
(recursion)
– move the bottom disk to
the desired peg
– move all n-1 disks from
the spare to the desired
peg (recursion)
4-20
The Game of Hex

B
W
W
B
Objective: connect your pair of the opposite sides of
the board with stones of your color
4-21
The Game of Hex (cont’d)
W
Each cell has
six “logical”
neighbors
B
B
W
Computer representation of the board in a
2-D array
4-22
The Game of Hex (cont’d)


 
 



  
To detect a win, determine whether any “blob”
(connected group of stones) touches the
opposite sides
4-23
The Game of Hex (cont’d)

This kind of task falls into the category of “area
fill” tasks


 
 
 
 





  

  
4-24
Review:

What is recursion?

How is recursion implemented in a computer?

What kinds of applications especially benefit from
recursion?

Give an example of a recursive method that can
be easily programmed with iterations.

Give an example of a method that would be rather
hard to program without recursion.
4-25
Review (cont’d):

Give an example of a method that is too slow in a
naïve recursive implementation.

What mathematical tool is very useful for
understanding recursive methods and proving
them correct?

What is the number of moves necessary to solve
the Towers of Hanoi puzzle with 1, 2, 3, ... n
disks? How would you prove your hypothesis?

Can you come up with an idea for a recursive
algorithm for “area fill”?
4-26