3 Recursion
3 Recursion
1
LEARNING OUTCOMES
2
SCOPE
The concept of recursion
How to write recursive methods
Recursion vs. Iteration
Recursive methods
Common errors in writing recursive methods
Analyzing recursive algorithms
3
WHAT IS RECURSION?
In some problems, it may be better to define the problem in terms of the problem itself.
Recursion is a problem-solving approach, that leads to elegant solutions to problems that are
difficult
to solve using simple loops.
The main idea is to split a problem into one or more simpler versions of itself
4
EXERCISE
(To a student in the front row)
How many students are behind you in your
"column" in the classroom?
5
THE IDEA
Recursion is all about breaking
a big problem into smaller
occurrences of that same
problem.
6
RECURSIVE
ALGORITHM
Number of people behind me:
If there is someone behind me,
ask him/her how many people are
behind him/her.
When they respond with a value N, then I will
answer N + 1.
7
Mathematical formulas are often expressed
recursively. N!, for any positive integer N, is defined
as the product of all integers between 1 and N
inclusive
N * N-1 * N-2 * … * 1 = N * (N-1)!
RECURSION IN This definition can be expressed recursively:
MATH 1! = 1
N! = N * (N-1)!
A factorial is defined in terms of another factorial
until the base case of 1! is reached
8
RECURSION IN PROGRAMMING
Recursion is a programming technique in which a method calls itself to fulfill its purpose.
When a method invokes itself, it is called a RECURSIVE METHOD
If the method is called with a complex problem, it typically divides the problem into two
conceptual parts
a part that the method knows the solution for it; and
a part that it does not know how to solve it but rather how to get it reach the solvable part.
Each call sets up a new execution environment, with new parameters and new local variables
As always, when the method completes, control returns to the method that invoked it (which
may be another instance of itself).
9
RECURSIVE METHOD STRUCTURE
Most recursive methods will look like:
10
DESIGNING A RECURSIVE SOLUTION
1. At least one “small” case that you can solve directly
2. A way of breaking a larger problem down into:
One or more smaller subproblems
Each of the same kind as the original
11
THREE-QUESTION METHOD OF VERIFYING
RECURSIVE FUNCTIONS
Base-Case Question: Is there a non-recursive way out of the function? i.e. What
is/are the case(s) for which you know solution(s)?
Smaller-Caller Question: Does each recursive function call involve a smaller case of
the original problem leading to the base case?
General-Case Question: Assuming each recursive call works correctly, does the whole
function work correctly?
12
RECURSIVE PROGRAMMING
Example: A recursive method for computing x!
long factorial (int x) {
if (x == 0)
return 1; //base case
else
return x * factorial (x – 1); //recursive case
}
When any function is called, the run-time stack is used. An activation record (stack
frame) is placed on this stack for the function call.
14
STACK ACTIVATION FRAMES
The activation record stores the return address for this function call, and also the
parameters, local variables, and the function’s return value, if non-void.
The activation record for a particular function call is popped off the run-time stack
when the final closing brace in the function code is reached, or when a return
statement is reached in the function code.
At this time the function’s return value, if non-void, is brought back to the calling block
return address for use there.
15
RECURSIVE TRACING: EXAMPLE1
Consider the following recursive method:
mystery(648):
public static int mystery(int n) {
if (n < 10) { ▪ int a = 648 / 10; // 64
return n; ▪ int b = 648 % 10; // 8
} else { ▪ return mystery(a + b); // mystery(72)
int a = n / 10;
mystery(72):
int b = n % 10;
▪ int a = 72 / 10; // 7
return mystery(a + b);
▪ int b = 72 % 10; // 2
}
▪ return mystery(a + b); // mystery(9)
}
mystery(9):
What is the result of the following call? ▪ return 9;
mystery(648)
16
RECURSIVE TRACING: EXAMPLE2
Tracing the recursive calls of the factorial(3) on the run-time stack
17
MORE RECURSIVE METHODS- SUM()
Consider the problem of computing the sum of all the integers between 1 and N, inclusive:
If N is 5, the sum = 1 + 2 + 3 + 4 + 5
This problem can be expressed recursively as:
The sum of 1 to N = N plus the sum of 1 to N-1
A recursive method that computes the sum of N :
18
EXAMPLE- SUM() - CONT.
Tracing the recursive calls of the sum method
19
MORE RECURSIVE METHODS- POWER()
From mathematics, we know that
20 = 1 and 2 5 = 2 * 24 public static int Power ( int x, int n )
In general, {
if ( n == 0 )
x0 = 1 and xn = x * xn-1 return 1; // base case
for integer x, and integer n > 0.
else // general case
return ( x * Power ( x , n-1 ) ) ;
Here we are defining xn recursively, in }
terms of xn-1
20
WHY RECURSION?
For many, recursion may seem hard or impossible, however, recursion often provides elegant,
short algorithmic solutions to many problems in computer science and mathematics.
Usually recursive algorithms have less code; therefore, algorithms can be easier to write and
understand - e.g., Towers of Hanoi.
Sometimes recursion provides a much simpler solution. Obtaining the same result using
iteration requires complicated coding - e.g., Quicksort and Towers of Hanoi.
21
WHY RECURSION? CONT.
Recursive methods provide a very natural mechanism for processing recursive data
structures.
A recursive data structure is a data structure that is defined recursively – e.g., Tree.
Recursive solution can be much more readable and elegant than iterative solution to the same
problem.
However, avoid using excessively recursive algorithms even if the code is simple.
22
Both iteration and recursion are based on a control
statement:
23
Iteration and recursion each involve a termination test:
Iteration terminates when the loop-continuation condition fails
24
Recursion repeatedly invokes the mechanism, and
consequently the overhead, of method calls.
Can be expensive in terms of both processor time and memory
25
Linear(Single) vs. Tree(Multiple)
26
Recursion that only contains a single self-reference is
known as linear or single recursion. E.g.: Factorial
function
In the factorial function, each invocation of
TYPES OF factorial() makes at most one new recursive call
27
EXCESSIVE RECURSION
A recursive method is excessively
recursive if it repeats computations
for some parameter values.
28
IF a Function F calls itself. (i.e.) F calls F. Then this
recursion is Direct Recursion.
TYPES OF
static int Direct (int n){
if (n<=0)
return 0;
RECURSION: }
return n + Direct (n-1);
RECURSION if (n<=0)
return 0;
return n + Buddy (n-1);
}
29
NESTED AND NON-NESTED RECURSIVE METHODS
Nested recursion occurs when a method
is not only defined in terms of itself; but
it is also used as one of the parameters:
Example: The Ackerman function
The Ackermann function grows faster than a
multiple exponential function. public static long Ackmn(long n, long m){
if (n == 0)
return m + 1;
else if (n > 0 && m == 0)
return Ackmn(n – 1, 1);
else
return Ackmn(n – 1, Ackmn(n, m – 1));
}
30
In tail recursion, a single recursive call is the last
statement to be executed in the function.
TYPES OF In non-tail recursion, the recursive call is not the last
RECURSION: statement to be executed in the function.
31
CONVERTING TAIL-RECURSIVE METHOD TO
ITERATIVE
It is easy to convert a tail recursive method into an iterative one:
Tail recursive method Corresponding iterative method
public static void f1(int n) {
public static void f1(int n) {
System.out.print(n + " ");
for( int k = n; k >= 0; k--)
if (n > 0)
System.out.print(k + " ");
f1(n - 1);
}
}
32
COMMON ERRORS IN WRITING RECURSIVE
METHODS- CONT.
The method does not call itself directly or indirectly.
Non-terminating Recursive Methods (Infinite recursion):
No base case.
int badFactorial(int x) {
return x * badFactorial(x-1);
}
33
COMMON ERRORS IN WRITING RECURSIVE
METHODS- CONT.
Post increment and decrement operators must not be used since the update will not occur until AFTER the
method call - infinite recursion. public static int sumArray (int[ ] x, int index) {
if (index == x.length)return 0;
else
return x[index] + sumArray (x, index++);
}
Local variables must not be used to accumulate the result of a recursive method. Each recursive call has its
own copy of local variables.
public static int sumArray (int[ ] x, int index) {
int sum = 0;
if (index == x.length)return sum;
else {
sum += x[index];
return sumArray(x,index + 1);
}
}
34
COMMON ERRORS IN WRITING RECURSIVE
METHODS- CONT.
Wrong placement of return statement.
Consider the following method that is supposed to calculate the sum of the first n integers:
public static int sum (int n, int result) {
if (n >= 0)
sum(n - 1, n + result);
return result;
}
When result is initialized to 0, the method returns 0 for whatever value of the parameter n. The result
returned is that of the final return statement to be executed. Example: A trace of the call sum(3, 0) is:
35
COMMON ERRORS IN WRITING RECURSIVE
METHODS- CONT.
A correct version of the method is:
public static int sum(int n, int result){
if (n == 0)
return result;
else
return sum(n-1, n + result);
}
36
COMMON ERRORS IN WRITING RECURSIVE
METHODS- CONT.
The use of instance or static variables in recursive methods should be avoided.
Although it is not an error, it is bad programming practice. These variables may be
modified by code outside the method and cause the recursive method to return
wrong result.
public class Sum{
private int sum;
37
ANALYZING RECURSIVE ALGORITHMS
To determine the order of a loop, we determine the order of the body of the loop
multiplied by the number of loop executions
Similarly, to determine the order of a recursive method, we determine the order of
the body of the method multiplied by the number of times the recursive method is
called
Example. Using a recursive solution to compute the sum of integers from 1 to N, the
recursive method is invoked N times and the method itself is O(1). So, the order of the
overall solution is O(n)
38
WHEN TO USE A RECURSIVE SOLUTION?
SHALLOW DEPTH: The depth of recursive calls is relatively “shallow” compared to the
size of the problem.
EFFICIENCY: The recursive version does about the same amount of work as the non-
recursive version. However, it may cause a higher overhead.
CLARITY: The recursive version is shorter and simpler than the non-recursive solution.
39
SUMMARY
◼ Recursion is a programming technique in which a method calls itself. A key to being able to program
recursively is to be able to think recursively.
◼ Any recursive definition must have a non-recursive part, called the base case, which permits the
recursion to eventually end (terminate).
◼ Each recursive call to a method creates new local variables and parameters.
◼ A careful trace of recursive processing can provide insight into the way it is used to solve a problem.
◼ Recursion is the most elegant and appropriate way to solve some problems, but for others it may be
less efficient than an iterative solution.
◼ The order of a recursive algorithm can be determined using techniques similar to those used in
analyzing iterative processing.
40
REFERENCES
◼ https://courses.cs.washington.edu›lectures›LectureA ›09-recursion
◼ https://slideplayer.com/slide/5043474/
41
ANY QUESTION???