Data Structures and Algorithms
Chapter 2 – Recursion
Dr. Georges Badr
Introduction
An algorithm uses one of the two methods
▪ iterative method, called also iterative function
- based on loops and terminates its execution when we exit the loop
▪ recursive method, called also recursive function
- this is when a function calls itself
one or many times to accomplish a given task
Motivation
▪ recursive functions simplify the implementation of algorithms
- they give an elegant and comprehensive representation
▪ iterative functions are more efficient in terms of performance
A recursive function can always be implemented in an iterative form
2
Analysis of the recursive method
To construct a recursive solution, we should
▪ understand the problem and find the parameters of the recursive function
▪ find the basic case(s)
- for which the solution(s) is known
- which is a termination condition of the recursion
- this will prevent infinity recursion
▪ find the general case : recursive call
- where the solution can be expressed in terms of (part of) itself
- which is a general expression
3
Example: factorial function
Write an iterative and recursive function to calculate the
factorial of a number
Iterative notation
0! = 1 General form:
1! = 1 n! = 1 if n = 0
2! = 1 x 2
3! = 1 x 2 x 3
n! = 1 * 2 * ... * (n-1) * n if n > 0
Recursive notation
General form:
4! = 4 x 3 x 2 x 1
= 4 x (3 x 2 x 1) n! = 1 if n = 0
4! = 4 x 3! n! = n * (n-1)! si n > 0
n! is defined in terms of itself
Given f(n)=n! and f(n-1)=(n-1)! Then f(n)=n*f(n-1)
4
0! = 1 Fact(5) = 5 * Fact (4)
1! = 1 = 1*1 =1*0!
Fact(4) = 4 * Fact(3)
2!= 1*2 = 2 * 1= 2 * 1!
3!= 1*2*3= 3*2!
Fact(3) = 3 * Fact(2)
4!=1*2*3*4= 4 * 3! Fact(2) = 2 * Fact(1)
n! = 1*2*3*4…= n*(n-1)! Fact(1) = 1 * Fact(0)
Fact(n) = n * Fact ( n-1)
Fact(0) = 1
5
Example: factorial function : Iterative and Recursive
int factorialIter (int n) { //iterative function
int facto=1;
for(int i=1;i<=n;i++)
facto=i*facto;
return facto;
}
int factorial (int n){ //recursive function Output
if (n <= 1) // base case
return 1; 0! = 1
return n*factorial (n-1); // recursive call 1! = 1
} 2! = 2
3! = 6
int main(){
int n;
4! = 24
for(int n=0; n<=10; n++) 5! = 120
cout<<n<<"! = "<<factorial(n)<<endl; 6! = 720
return 0; 7! = 5040 6
} 8! =
Example: factorial function Recursive call representation
Recursive call
1 2 3 4
factorial (4) factorial(3) factorial(2) factorial(1)
n=4
4*factorial(3); n = 3;
3*factorial (2); n = 2;
2*factorial (1); n = 1;
1 return 1;
2 return 2*1;
6 return 3*2;
24 return 4*6;
7
Power function
Write an iterative and recursive function that calculates xn for n>0
Iterative notation
xn = x*x*…x*x ; n multiplications by x
Recursive notation
▪ basic case: x1=x or x0 =1
▪ general case: xn = x*xn-1
If n>=0, the basic case is x0=1
8
x^n = ?
x^0 = 1
x^1 = x = x * 1 = x * x^0
x^2 = x * x = x * x^1
x^3 = x * x * x = x * x^2
x^4 = x * x * x * x = x * x^3
…
x^n = x* x*x*x…*x = x * x^(n-1)
x^n = 1 if n = 0
= x * x^(n-1) if n !=0
9
Power function: Iterative and recursive
double powerIter(int x, int n) {
double pow=1;
for(int i=1;i<=n;i++)
pow=x*pow;
return pow;
}
//x^n=x*x^(n-1)
double power(int x, int n){
if (n == 0)
return 1;
if (n == 1)
return x;
return x*power(x,n-1);
}
10
Power function: Recursive calls representation
Recursive calls
1 2 3 4
power(3,4) power(3,3) power(3,2) power(3,1)
x=3; n=4;
3*power (3,3); x=3; n=3;
3*power (3,2); x=3; n=2;
3* power (3,1); x=3; n=1;
3 return 3;
9 return 3*3;
27 return 3*9;
81 return 3*27;
11
Power function: 2nd method, more efficient
If n is even: xn=(xn/2)2; e.g.: 34=(32)2
If n is odd: xn=(x(n-1)/2)2*x; e.g.: 35=(32)2*3
Then the recursive calls number will be reduced almost to half
double power(int x, int n){
double res;
if (n == 1)
return x;
if(n%2==0){
res=power(x,n/2);
return res*res;
}
else {
res=power(x,n/2);
return x*res*res;
}
}
12
power (3,4)
x=3, n=4, even
res = power (3,2) → power (3,2)
return res*res x=3, n=2, even
res = power (3,1) → power (3,1)
return res*res x=3, n=1
return 3
power(2,5)
x=2, n=5, odd
res = power(2,2) → power(2,2)
return 2*res*res x=2, n=2, even
res = power(2,1) → power(2,1)
return res*res x=2, n=1
return 2
13
Sum function in an array
Write an iterative and recursive functions that calculates
Sn=tab[0]+tab[1]+…+tab[n-1] where n is the elements number
Recursive notation:
▪ basic case: S1=tab[0]
▪ general case: Sn=Sn-1+tab[n-1]
int sumIter(int *tab, int n) {
int s=0;
for(int i=0;i<n;i++)
s+=tab[i];
return s;
}
14
1st method
int sum(int *A, int n, int i) Sum ( 1 2 3 4 5 6 )
{
if(i == n) = 1 + Sum( 2 3 4 5 6 )
return 0;
return A[i] + sum (A, n, i+1); = 1 + 2 + Sum( 3 4 5 6 )
}
= 1 + 2 + 3 + Sum( 4 5 6 )
Main call: S = sum (tab, 6, 0);
= 1 + 2 + 3 + 4 + Sum( 5 6 )
= 1 + 2 + 3 + 4 + 5 + Sum( 6 )
Sum([1,2,3,4,5,6]) return 1 + S([2,3,4,5,6]), return 1 + 20 → return 21
Sum([2,3, 4, 5, 6]) return 2 + S ([3, 4, 5, 6]), return 18 + 2 → return 20
= 1 + 2 + 3 + 4 + 5 + 6 + Sum( )
Sum([3, 4, 5, 6]) return 3 + S([4, 5, 6]), return 3 + 15 → return 18
Sum([4, 5, 6]) return 4 + S([5, 6 ]), return 4 + 11 → return 15
= 1 + 2 + 3 + 4 + 5 + 6 + 0 = 21
Sum([5, 6]) return 5 + S([6]), return 5 + 6 → return 11
Sum([6]) return 6 + S([]), return 6 + 0 → return 6
Sum([]) return 0
15
2nd method
int Sum(int *A, int n) Sum ( 1 2 3 4 5 6 )
{
if(n==0) = 6 + Sum( 1 2 3 4 5 )
return 0;
return A[n-1]+Sum(A,n-1); = 6 + 5 + Sum( 1 2 3 4 )
}
= 6 + 5 + 4 + Sum( 1 2 3 )
= 6 + 5 + 4 + 3 + Sum( 1 2 )
Sum([1,2,3,4,5,6]) return 6 + Sum([1,2,3,4,5]), return 6 + 15 → return 21 = 6 + 5 + 4 + 3 + 2 + Sum( 1 )
Sum([1,2,3, 4, 5]) return 5 + Sum([1,2,3,4]), return 5 + 10 → return 15
Sum([1,2,3,4]) return 4 + Sum([1,2,3]), return 4 + 6 → return 10 = 6 + 5 + 4 + 3 + 2 + 1 + Sum( )
Sum([1,2,3]) return 3 + Sum([1,2]), return 3 + 3 → return 6
Sum([1,2]) return 2 + Sum([1]), return 2 + 1 → return 3 = 6 + 5 + 4 + 3 + 2 + 1 + 0 = 21
Sum([1]) return 1 + Sum([]), return 1 + 0 → return 1
Sum([]) return 0
16