CS2320: DATA
STRUCTURES &
ALGORITHMS
Recursive Definitions
◻ Consider the following list of numbers:
24, 88, 40, 37
◻ Such a list can be defined recursively:
A LIST is a: number
or a: number comma LIST
◻ That is, a LIST can be a number, or a number
followed by a comma followed by a LIST
◻ The concept of a LIST is used to define itself
Tracing the recursive definition of a
list
LIST: number comma LIST 24 , 88, 40, 37
number comma LIST 88 , 40, 37
number comma LIST 40 , 37
number
37 3
What 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
Recursive Thinking
◻ Recursion is a programming technique in which a
method can call itself in order to fulfill its purpose
◻ A recursive definition is one which uses the word
or concept being defined in the definition itself
◻ In some 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
Infinite Recursion
◻ All recursive definitions must have a non-recursive part ◻ If they don't, there is no way to terminate the recursive
path
◻ A definition without a non-recursive part causes infinite
recursion
◻ This problem is similar to an infinite loop -- with the definition itself causing the infinite “looping”
◻ The non-recursive part often is called the base case
Parts of a Recursive Definition
Every recursive definition contains two parts:
◻ a base case, which is non-recursive and,
consequently, terminates the recursive application of the rule.
◻ a recursive case, which reapplies a rule.
Direct vs. Indirect 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 invokes m1 again
◻ This is called indirect recursion
◻ It is often more difficult to trace and debug
Direct vs. Indirect Recursion
m1 m2 m3
m1 m2 m3
m1 m2 m3
Phases of Recursion
Forward Phase:Every recursion has a forward phase in which a call at every level, except the last, spins off a call to the next level, and waits for the latter call to return control it. ◻ Backward Phase:
Every recursion has a backtracking phase in which a call at every level, except the first, passes control back to the previous level, at which point the call waiting at the
previous level wakes up and resumes its work.
Examples: Simple problems
◻ Summation
◻ Factorial ◻ Fibonacci
Summation
The sum of 1 to N, defined recursively
public int sum (int num) {
int result; if (num == 1) result = 1; else
result = num + sum(num-1); return result;
}
Base case
Recursive case
Recursive calls to the
sum
method
main sum sum sum sum result = 4 + sum(3) sum(4) sum(3) sum(2) sum(1) result = 1 result = 3 + sum(2) result = 2 + sum(1) 14Factorial
◻ Mathematical formulas are often expressed
recursively
◻ 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:
1! = 1
N! = N * (N-1)!
◻ A factorial is defined in terms of another factorial
until the base case of 1! is reached
Factorial Function
◻ N is 1 x 2 x 3 x ... x N – 1 x N
Computing the Factorial
◻ A recursive program implements a recursive definition.
◻ The main work in writing a recursive method to solve a specific problem is to define base cases.
Computing the Factorial (Cont.)
Fibonacci Sequence
fibn – 1 + fibn – 2, if n > 1 recursive case
fibn =
0, if n == 0 base case 1, if n == 1 base case
Fibonacci Sequence
◻ Definition of F(4) spins off two chains of
recursion, one on F(3) and another on F(2).
◻ Every chain either ends in F(0) or F(1)
Computing the Fibonacci Sequence
Computing the Fibonacci Sequence (Cont.)
◻ Every call waits on two subsequent calls.
These waits are not simultaneous.
For every call there is a wait-wakeup-wait-wakeup cycle.
■ Except the F(0) and F(1). ■ There are two forward
phases and two backtracking phases.
Avoiding Recursion
Avoiding Recursion
Avoiding Recursion
A Simple Solution to a Difficult
Problem
◻ The Towers of Hanoi
26
Towers of Hanoi: An Application
There are three towers or pegs, A, B, and C, and a pile of disks of various sizes.
■ The disks start on peg A.
■ Move all the disks from peg A to C,
using B as an intermediate.
■ (a) only one disk can be moved at a
time.
■ (b) a larger disk can never go on top
of a smaller one.
Towers of Hanoi: Base cases
◻ The smallest instance of the problem is when there
is only one disk in the stack.
Simply move the disk from peg A to C.
◻ With 2 disks:
Top disk moves to B
Bottom disk moves to C.
Top disk moves from B to C.
Towers of Hanoi: Recursive cases
With three disks:
■ We move two disks out of the way
from A to B.
■ We move the bottom disk from A
to C.
■ We move the two disks from B to
C.
We are not allowed to move two disks at a time.
Sub-problems requires us to move two disks from one beg to another, which we already know how to do.
Towers of Hanoi: Recursive
cases(Cont.)
◻ Two-disk problem moved two disks from A to C.
Three-disk problem, the first two-disk sub-problem moves disks from A to B.
Second two-disk sub-problem moves disks form B to C.
Providing the source destination, and intermediate pegs can generalize the sub-problem.
Towers of Hanoi: All together
◻ Recursive definition of towers of Hanoi solution for
any n.
Solve the towers of Hanoi problem for n – 1, with source peg A, destination peg B, intermediate peg C. Move a disk from A to C.
Solve the towers of Hanoi problem for n – 1, with source peg B, destination peg C, intermediate peg A.
Towers of Hanoi: An example
• The sequence of moves for solving the Towers of Hanoi problem with three disks.
Continued →
Towers of Hanoi: An example
(Cont.)
• (Continued) The sequence of moves for solving the Towers of Hanoi problem with three disks.
Towers of Hanoi: An example
(Cont.)
• (Continued) The smaller problems in a recursive solution for four disks
Towers of Hanoi: The algorithm
Algorithm to solve Towers of Hanoi PuzzleAlgorithm solveTowers (numberOfDisks, startPole, tempPole, endPole) if (numberOfDisks == 1)
Move disk from startPole to endPole else
{
solveTowers (numberOfDisks - 1, startPole, endPole, tempPole) Move disk from startPole to endPole
solveTowers (numberOfDisks - 1, tempPole, startPole, endPole) }
35
Recursion vs. Iteration
◻ Comparison of elements of a loop and a recursive
function
Loop Recursive Method
loop control variable method input loop exit condition base case
loop entry condition recursive case
loop body method body
Recursion vs. Iteration
◻ 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
◻ The iterative version is easier to understand (in fact
there is a formula that is superior to both recursion and iteration in this case)
◻ You must be able to determine when recursion is
the correct technique to use
Recursion vs. Iteration
◻ Every recursive solution has a corresponding
iterative solution
◻ For example, the sum of the numbers between 1
and N can be calculated with a loop
◻ Recursion has the overhead of multiple method
invocations
◻ However, for some problems recursive solutions are often more simple and elegant than iterative solutions
Drawbacks of Recursion
◻ Stack space that is used to implement it.
Every recursive method call produces a new instance of the method, with a new set of local variables
(including parameters).
Computing the factorial of a number.
■ Local information pertaining to each of the calls to fact(N),
fact(N-1), etc. all the way down to fact(2) is stored on stack.
■ fact (N) would consume O(N) worth of stack space.
Drawbacks of Recursion (Cont.)
◻ Certain computations may be performed
redundantly.
The Fibonacci sequence.
■ In computing F(4), F(2) is computed twice.
■ F(5)?
■ F(3) is computed twice, which involves a computation of F(2),
and there is another computation of F(2) by itself.
■ Things thus get worse as we recursively compute the
Fibonacci sequence for bigger and bigger numbers.
■ Not to mention the stack space used.
Drawbacks of Recursion (Cont.)
◻ One has to weigh the simplicity of code delivered
by recursion against its drawbacks.
When iterative solution is obvious.
There are several problems for which such iterative solutions are not obviously forthcoming.
Summary
◻ Defining the base case is vital.
◻ Building on the base case(s) to solve a problem results in defining the recursive case.
◻ It is not always right to use recursive solutions. Applying recursive on simple problems may result in inefficiency in terms of time and redundancy (Fibonacci).
◻ Recursion is simple, efficient, and elegant solution if applied to the right problem (Towers of Hanoi).