Recursion PDF
Recursion PDF
Recursion PDF
• What is Recursion?
• Recursive data structures
• Recursive data algorithms
• A recursive function knows when to stop calling itself once a base case is
reached.
e.g. //print numbers 1 to n backwards
int print(int n)
{
if ( n = = 0) // this is the terminating base case
return 0;
else {
System.out.print(“”+n+” “);
return print(n-1); // recursive call to itself again
}
}
• The recursion step can result in many more such recursive calls as the method keeps
dividing each problem it is called with into two smaller problems.
• Each time the function calls itself with a slightly simpler version of the original problem.
• This sequence of smaller problems must eventually converge on the base case.
1. One (or more) base cases that are not recursive, i.e. we can
directly give a solution:
if (n==0)
return 0;
return print(n-1);
• NOTE: - The base case(s) should always be checked before the recursive calls.
- Most of the time, a recursive function will usually return something.
e.g.
// example of a badly defined recursive function
int Bad_recursion(n)
{
int x = Bad_recursion(n-1); // Bad!!!
if (n == 1)
return 1;
else
return n*x;
}
• Once a method ends (i.e. returns some data), the copy of that returning method is
removed from memory
• In our previous example, if we called the print function with n=4, visually our memory
assignments may look like such :
Original calling method
print(4)
print(3)
returns 0 print(2)
returns 0 print(1)
returns 0 print(0)
Returns 0 to main calling program
returns 0
• Some problems are best suited for recursive solutions while others are not.
• Recursion is a complex topic and recursive algorithms can get quite complex.
• We are going to look at some simple problems that can be solved recursively.
n! = n*(n-1)*(n-2)…3*2*1
• Mathematical explanation :
n! = 1, if n = 0
n * (n-1)! if n > 0
• Example :
6! = 6*5*4*3*2*1 = 720
n! = 1, if n = 0
n * (n-1)! if n > 0
• From this we can obtain both our base and recursive cases:
- Base Case :
if(n <= 1)
return 1;
- Recursive Case:
return n*factorial(n-1);
• Now that we know both our base and recursive cases we can write our factorial method:
int factorial(int n)
{
if (n <=1) // the base case
return 1
else
return n * factorial(n-1); // the recursive case
}
Final result = 24
4! 4!
4*6 24 returned
4 * 3! 4 * 3!
3 * 2! 3*2 6 returned
3 * 2!
2 * 1 2 returned
2 * 1! 2 * 1!
1 returned
1 1
Programming and Data Structures 11
Recursion Vs. Iteration
• So which way is better? – iteration or recursion?
• Usually, a recursive approach more naturally mirrors the problem at hand. So,
a recursive approach makes it simpler to tackle a problem which may not have
the most obvious of answers.
• However, recursion carries an overhead that for each recursive call needs space
on the stack frame.
• This extra memory need can be quite processor intensive and consume a lot of
memory if recursion is nested deeply
• Iteration does not have this overhead as it occurs within the method so the
overhead of repeated method calls and extra memory is ommitted.
Programming and Data Structures 12
Recursion Vs. Iteration - Differences
Recursion Iteration
• terminates when a base case is reached. • Terminates when a condition is proven to be
false.
• Each recursive call requires extra space
• Each iteration does not require any extra space
on the stack frame (i.e. memory).
as it resides in the same method.
• If we get infinite recursion, we will • an infinite loop could potentially loop forever
eventually run out of memory, resulting in since there is no extra memory being created.
a stack overflow.
• solutions to some problems are easier to • Iterative solutions to a problem may not
formulate recursively. always be as obvious as a recursive solution.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 …
begins with a 0 and 1 and has the property that each subsequent Fibonacci number is
the sum of the previous two Fibonnacci numbers
0 if n = 0
fib(n) = 1, if n = 1
fib(n-1) + fib(n-2), if n > 1
- Base case(s) :
if (n == 0) or (n == 1)
return n;
- Recursive case(s) :
return fib(n-1) + fib(n-2);
• Note: In order to produce a fibonacci series we would iteratively call this function to produce the
required Fibonacci number in the series
returns 1 returns 0
• Each level of recursion in the fibonacci function has a doubling effect on the
number of calls.
• Calculating the 20th Fibonacci number would require on the order of about a
million calls.
• Calculating the 30th Fibonacci number would require around a billion calls.
Fib(x)
if knownFib[x] <> unknown //if fib number x is known
return knownF[x] // return known result
knownF[x] = t // fib number x now known so put into our known array
return knownF[x] // return fib number x
• Note the index of our knownFib array represents each fib number x so that x can be used here as
an index into our knownFib array.