Transcript Lecture 11

ICS103 Programming in C
Lecture 11: Recursive Functions
1
Outline
•
•
•
•
•
•
•
Recursive functions and Recursion
Writing a recursive function
Recursion vs Repetition
Tracing Recursive Functions
Examples
Mutually recursive functions
Common errors
2
What is a recursive function?
• A recursive function is a function that calls itself
either directly or indirectly
• In C, any function can call itself
Example: What is the output of the following
program?
#include <stdio.h>
main() {
printf(" Going around! ");
main();
}
3
Why recursive functions?
• Recursion is a powerful problem solving technique
• Many mathematical functions can be defined recursively
• Example: Factorial Function
 5! = 5 * 4 * 3 * 2 * 1 or 5! = 5 * 4!
 0! = 1
base case
 in general
1
n=0
n! =
n (n-1)!
n>0
recursive case
• By re-appling the recursive case(s), solution will move closer and
eventually reach the base case(s)
4
Writing a recursive function
if this is a base case
solve it
else
redefine the problem using recursion
• Recursive functions generally involve an if statement
• The if-branch is the base case, while the else-branch is
the recursive case.
• The recursive case provides the repetition needed for
the solution and the base case provides the termination.
• For the recursion to terminate, each recursive call must
be moving closer to a base case.
5
Recursion vs Repetition
Computing the factorial of a number n
Recursive version
int factorial (int n){
if (n == 0)
return 1;
else
return n * factorial (n-1);
}
Iterative version
int factorial (int n){
int i, product=1;
for (i=n; i>1; --i)
product=product * i;
return product;
}
6
Tracing Recursive Functions
Executing recursive algorithms goes through two phases:
 Expansion in which each recursive step is applied until reaching a base step
 “Substitution” in which the solution is constructed backwards starting with the base step(s)
factorial(4)
= 4 * factorial (3)
= 4 * (3 * factorial (2))
Expansion
phase
= 4 * (3 * (2 * factorial (1)))
= 4 * (3 * (2 * (1 * factorial (0))))
= 4 * (3 * (2 * (1 * 1)))
= 4 * (3 * (2 * 1))
= 4 * (3 * 2)
=4*6
= 24
Substitution
phase
7
Example 1: Multiplication
Write a recursive function to compute m x n (where both
m and n are integers)
• The best way to go about this is to identify the base
case and the recursive case.
• base case: if n is 1, then m*n = m
• recursive case: if n > 1, then m*n = m + m * (n-1).
m,
n=1
m*n
m + m*(n-1), n>1
8
Example 1: Multiplication (cont.)
#include <stdio.h>
int multiply(int m, int n);
int main(void) {
int num1, num2;
printf("Enter two integer numbers to multiply: ");
scanf("%d%d", &num1, &num2);
printf("%d x %d = %d\n", num1, num2, multiply(num1, num2));
system("pause");
return 0;
}
int multiply(int m, int n) {
if (n == 1)
return m;
else
return m + multiply(m, n
}
/* simple case */
- 1);
/* recursive step */
9
Example 1: Multiplication (cont.)
multiply(5,4)
Expansion
phase
= 5 + multiply(5, 3)
= 5 + (5 + multiply(5, 2))
= 5 + (5 + (5 + multiply(5, 1)))
= 5 + (5 + (5 + 5))
= 5 + (5 + 10)
= 5 + 15
= 20
Substitution
phase
10
Example 2: Power function
• Suppose we wish to define our own power function that
raises a double number to the power of a non-negative
integer exponent. xn , n >= 0.
• The base case is if n is 0. The answer is 1.
• The recursive case is: xn = x * xn-1.
1, n = 0
xn
x * x n-1, n>0
11
Example 2: Power function (cont.)
#include <stdio.h>
double pow(double x, int n);
int main(void) {
double x;
int n;
printf("Enter double x and integer n to find pow(x,n): ");
scanf("%lf%d", &x, &n);
printf("pow(%f, %d) = %f\n", x, n, pow(x, n));
system("pause");
return 0;
}
double pow(double x, int n) {
if (n == 0)
return 1;
else
return x * pow(x, n
}
/* simple case */
- 1);
/* recursive step */
12
Example 3: Fibonacci Function
• Suppose we wish to define a function to compute the nth term of the
Fibonacci sequence.
• Fibonacci is a sequence of number that begins with the term 0 and 1
and has the property that each succeeding term is the sum of the two
preceding terms:
• Thus, the sequence is: 0, 1, 1,2,3,5,8,13,21,34 …
•
Mathematically, the sequence can be defined as:
n, n = 0, 1
fib(n)
fib(n-1) + fib(n-2) n>1
13
Example 3: Fibonacci Function (cont’d)
#include <stdio.h>
int fib(int n);
int main(void) {
int n;
printf("Enter an integer n to find the nth fibonacci term: ");
scanf("%d", &n);
printf("fibonacci(%d) = %d\n", n, fib(n));
system("pause");
return 0;
}
int fib(int n) {
if (n == 0 || n== 1)
return n;
else
return fib(n-1) + fib(n-2);
}
/* simple case */
/* recursive step */
14
Example 3: Fibonacci Function (cont’d)
• Another way to trace a recursive function is by drawing its recursive tree
• Example: The recursive tree for fib(6) is:
15
Example 4
Draw a recursive tree for the call display(3) and determine the program
output
#include <stdio.h>
void display(int);
int main(void){
display(3);
system("pause");
return 0;
}
void display(int n){
if(n > 0){
printf("RIYADH\n");
display(n - 1);
printf("DAMMAM\n");
}
}
• The blue numbers indicate the order in which the
strings are printed.
• Hence the output is:
RIYADH
RIYADH
RIYADH
DAMMAM
DAMMAM
DAMMAM
16
Example 5: Mutually recursive functions
• Mutually recursive Trigonometric functions
double sin(double x){
if(x < 0.0000001)
return x - (x*x*x)/6;
else{
double y = tan(x/3);
return sin(x/3)*((3 - y*y)/(1 + y*y));
}
}
double tan(double x){
return sin(x)/cos(x);
}
double cos(double x){
double y = sin(x);
return sqrt(1 - y*y);
}
17
Example 6: Mutually recursive functions
• Mutually recursive functions to check whether a
positive integer is even or odd
int isEven(int n) {
if (n==0)
return 1;
else
return(isOdd(n - 1));
}
int isOdd(int n) {
Exercise:
return (! isEven(n));
1. Draw the recursive tree for:
}
(a) isEven(2)
(b) isEven(3)
(c) isOdd(5)
2. Write a main method to test the above mutually recursive functions
18
Some Common Errors in Writing Recursive Functions
1. The function does not call itself directly or indirectly.
2. Non-terminating Recursive Functions (Infinite recursion):
(a) No base case.
int badFactorial(int x) {
return x * badFactorial(x-1);
}
(b) The base case is never reached for some parameter values.
int anotherBadFactorial(int x) {
if(x == 0)
return 1;
else
return x*(x-1)*anotherBadFactorial(x - 2);
// When x is odd, we never reach the base case!!
}
19
Some Common Errors in Writing Recursive Functions (cont’d)
3. Using a local variable (a variable declared within a function) wrongly to accumulate
the result of a recursion
int sumFirst_n_PositiveInts(int n) {
int sum = 0;
if(n == 1)
return sum;
else{
sum = sum + n;
return sumFirst_n_PositiveInts(n – 1);
}
}
In the above example, the local variable sum is reinitialized to zero in each recursive call
(each call has its own sum). Hence, the returned value is 0.
One correct solution is:
int sumFirst_n_PositiveInts(int n) {
if(n == 1)
return n;
else
return n + sumFirst_n_PositiveInts(n – 1);
}
20