Recursive Fns in C
Recursive Fns in C
1
Recursion
A process by which a function calls itself repeatedly
Either directly.
X calls X
Or cyclically in a chain.
X calls Y, and Y calls X
3
For a problem to be written in recursive form, two
conditions are to be satisfied:
It should be possible to express the problem in
recursive form
Solution of the problem in terms of solution of the same
problem on smaller sized data
The problem statement must include a
stopping/terminating condition
The direct solution of the problem for a small enough
size
Stopping/Terminating
fact(n) = 1, if
condition
= n* n = 0 if
fact(n-1), Recursive definition
4
n>0
Examples:
Factorial:
fact(0) = 1
fact(n) = n
* fact(n-1),
if n > 0
GCD:
gcd (m, m)
=m
gcd (m, n) = gcd (m%n, n), if m > n
gcd (m, n) = gcd (n, n%m), if m < n
Fibonacci series (1,1,2,3,5,8,13,21,….)
fib (0) = 1
19
fib (1) = 1
Factorial
long int fact (int n)
{
if (n
== 1)
return (1);
else
return
(n *
fact(n-1)); 20
Factorial Execution
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (3
= = 1) return (1);
else return (3
* fact(2));
long int fact (int n)
{
if (n = = 1) return
(1); else return (n
* fact(n-1));
}
24
Factorial Execution
fact(4)
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (3
= = 1) return (1);
else return (3
* fact(2));
long int fact (int n)
{ if
if (n = = 1) return
(1); else return (n (2 = = 1) return (1);
else return
* fact(n-1));
} (2 * fact(1));
25
Factorial Execution
fact(4)
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (3
= = 1) return (1);
else return (3
* fact(2));
long int fact (int n)
{ if
if (1 = = 1) return
if (n = = 1) return
(1); (1);
(2 = = 1) return
(1); else return (n
else return
* fact(n-1));
} (2 * fact(1));
26
Factorial Execution
fact(4)
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (3
= = 1) return (1);
else return if (2(3= = 1) return
* fact(2)); (1); else return 1
long int fact (int n) (2 * fact(1));
{
if (1 = = 1) return
if (n = = 1) return
(1);
(1); else return (n
* fact(n-1));
}
27
Factorial Execution
fact(4)
if (4 = = 1) return
(1); else return
(4 * fact(3));
if (3 = = 1) return
(1); else return 2
(3 * fact(2));
if (2 = = 1) return
(1); else return 1
long int fact (int n) (2 * fact(1));
{
if (1 = = 1) return
if (n = = 1) return
(1);
(1); else return (n
* fact(n-1));
}
28
Factorial Execution
fact(4
)
if (4 = = 1) return
(1); else return 6
(4 * fact(3));
if (3 = = 1) return
(1); else return 2
(3 * fact(2));
if (2 = = 1) return
(1); else return 1
long int fact (int n) (2 * fact(1));
{
if (1 = = 1) return
if (n = = 1) return
(1);
(1); else return (n
* fact(n-1));
}
29
Factorial Execution
fact(4 24
)
if (4 = = 1) return
(1); else return 6
(4 * fact(3));
if (3 = = 1) return
(1); else return 2
(3 * fact(2));
if (2 = = 1) return
(1); else return 1
long int fact (int n) (2 * fact(1));
{
if (1 = = 1) return
if (n = = 1) return
(1);
(1); else return (n
* fact(n-1));
}
30
Example: Finding max in an array
int findMax(int A[ ], int n) Terminating condition. Small
{ size problem that you know
int temp; how to solve directly without
calling any functions
if (n==1)
{
r
e Recursive call. Find the max
t in the first n-1 elements (exact
u same problem, just solved on
r a smaller array).
n
A
[
0
Important things to remember
Think how the whole problem (finding max of n
elements in A) can be solved if you can solve the exact
same problem on a smaller problem (finding max of
first n-1 elements of the array). But then, do NOT think
how the smaller problem will be solved, just call the
function recursively and assume it will be solved.
When you write a recursive function
First write the terminating/base condition
Then write the rest of the function
Always double-check that you have both
Back to Factorial: Look at the variable
addresses (a slightly different program) !
int main()
Output
{
int x,y; 4
scanf("%d",&x); F: data = 4, &data =
y = fact(x); 3221224528 &val =
printf ("M: x= %d, y = %d\n",
3221224516
x,y); return 0;
F: data = 3, &data =
}
int fact(int data) 3221224480 &val =
{ int val = 1; 3221224468
printf("F: data = %d, &data = %u \n F: data = 2, &data =
&val = %u\n", data, &data, &val); 3221224432 &val =
if (data>1) val = data*fact(data-1);
3221224420
return val;
} F: data = 1, &data = 18
The memory addresses for the variable data are
different in different calls!
They are not the same variable.
Each function call will have its own set of variables, even if
the name of the variable is the same as it is the same
function being called
Change made to one will not be seen by the calling
function on return
19
int main()
{ Output
int x,y; 4
scanf("%d",&x); count = 1, data = 1
y = fact(x);
count = 1, data = 2
printf ("M: x= %d, y = %d\n",
count = 1, data = 3
x,y); return 0;
} count = 1, data = 4
int fact(int data) M: x= 4, y = 24
{
int val = 1, count = 0;
if (data>1) val = data*fact(data-1);
• Count did not change
count++; even though ++ done!
• Each call does it on its
printf(“count = %d, data = %d\n”,
count, data); own copy, lost on return
return val;
20
}
Fibonacci Numbers
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n –
1) otherwise;
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
37
int fib (int n) {
if (n == 0 || n == 1) Fibonacci recurrence:
return 1; fib(n) = 1 if n = 0 or 1;
return fib(n-2) +
} fib(n-1) ; = fib(n – 2) + fib(n –
1) otherwise;
fib (5)
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
1 1 1 1
1
fib (0) fib (1)
1 1
fib.c 23
int fib (int n) {
if (n==0 || n==1) Fibonacci recurrence:
return 1; fib(n) = 1 if n = 0 or 1;
return fib(n-2) +
} fib(n-1) ; = fib(n – 2) + fib(n –
8 1) otherwise;
fib (5)
3 5
fib (3) fib (4)
1 2 2 3
fib (1) fib (2) fib (2) fib (3)
1 2
1 1 1 1 1
fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)
1 1 1 1 1
1 1
fib (0) fib (1)
1 1
39
Example: Sum of Squares
int sumSquares (int m, int n)
{
int middle ;
if (m == n) return(m*m);
else
{
middle = (m+n)/2;
return
(sumSquares(m,middl
e)
+
sumSquar
40
es(middle
Annotated Call Tree
355
sumSquares(5,10)
110 245
sumSquares(5,7) sumSquares(58,10)
61 49 145 100
sumSquares(5,6) sumSquares(7,7) sumSquares(8,9) sumSquares(10,10)
25 36 64 81
sumSquares(5,5) sumSquares(6,6) sumSquares(8,8) sumSquares(9,9)
25 36 49 64 81 100 26
Example: Printing the digits of an Integer in
Reverse
Print the last digit, then print the remaining number in
reverse
Ex: If integer is 743, then reversed is print 3 first,
then print the reverse of 74
void printReversed(int i)
{
if (i < 10)
{ printf(“%d\n”, i);
return;
}
else {
printf(“%d”, i%10);
printReversed(i/10);
27 }
Counting Zeros in a Positive Integer
Check last digit from right
If it is 0, number of zeros = 1 + number of zeroes in
remaining part of the number
If it is non-0, number of zeros = number of zeroes in
remaining part of the number
int zeros(int number)
{
if(number<10) return 0;
if (number%10 == 0)
return(1+zeros(nu
mber/10));
else
return(zeros(number/
28 10));
Example: Binary Search
Searching for an element k in a sorted array A with n
elements
Idea:
Choose the middle element A[n/2]
If k == A[n/2], we are done
If k < A[n/2], search for k between A[0] and A[n/2 -1]
If k > A[n/2], search for k between A[n/2 + 1] and A[n-1]
Repeat until either k is found, or no more elements to
search
Requires less number of comparisons than linear
search in the worst case (log2n instead of n)
44
int binsearch(int A[ ], int low, int high, int k)
{
int mid;
printf(“low = %d, high = %d\n”, low, high);
if (low < high)
return 0;
mid = (low + high)/2;
printf(“mid = %d, A[%d] = %d\n\n”, mid, mid, A[mid]);
if (A[mid] == k)
return 1;
else {
if
(A[mid]
> k)
r
e
t
u 45
int main()
{
int A[25], n, k, i, found;
scanf(“%d”, &n);
for (i=0; i<n; i++) scanf(“%d”, &A[i]);
scanf(“%d”, &k);
found = binsearch(A, 0, n-1, k);
if (found == 1)
printf(“%d is present in the array\n”, k);
else
printf(“%d is not present in the array\
n”, k);
}
46
Output
8 8
9 11 14 17 19 20 23 27 9 11 14 17 19 20 23 27
21 14
low = 0, high = 7 low = 0, high = 7
mid = 3, A[3] = 17 mid = 3, A[3] = 17
low = 0, high = 2
low = 4, high = 7
mid = 1, A[1] = 11
mid = 5, A[5] = 20
low = 2, high = 2
low = 6, high = 7 mid = 2, A[2] = 14
mid = 6, A[6] = 23
14 is present in the array
low = 6, high = 5
21 is not present in the array
47
Static Variables int Fib(int n, int i)
{
int anotherBadFactorial(int x) {
int badSum2(int x)
if(x == 0)
return 1; {
else if(x==1) return 1;
return return(badSum2(x--));
x*(x- }
1)*anoth
erBadFa
Common Errors in Writing Recursive Functions
Mixing up loops and recursion
int anotherBadFactorial(int x) {
int i, fact = 0;
if (x == 0)
return 1;
else {
for (i=x;
i>0; i=i-
1) {
fact =
fact
+
x*an
In general,otherif you have recursive function calls within a
loop, thinkBadF carefully if you need it. Most recursive
actor
functions ial(x-
you will see in this course will not need this
1);
Recursion vs. Iteration
Repetition
Iteration: explicit loop
Recursion: repeated function calls
Termination
Iteration: loop condition fails
Recursion: base case recognized
Both can have infinite loops
Balance
Choice between performance (iteration) and good
software engineering (recursion).
52
Every recursive program can also be written without
recursion
Recursion is used for programming convenience, not
for performance enhancement
Sometimes, if the function being computed has a nice
recursive form, then a recursive code may be more
readable
53
How are function calls implemented?
The following applies in general, with minor variations
that are implementation dependent
The system maintains a stack in memory
Stack is a last-in first-out structure
54
int main()
{ int gcd (int x, int y)
…….. {
x = gcd (a, b); ……..
…….. ……..
} return (result);
}
Local
Activation Variable
record s
STACK
Return Value
Return Addr
3 times
Before call Call ncr Call fact fact returns ncr returns
56
What happens for recursive calls?
What we have seen ….
Space for activation record is allocated on the
stack when a function call is made
Space allocated for activation record is de- allocated
on the stack when the function returns
In recursion, a function calls itself
Several function calls going on, with none of the
function calls returning back
Space for activation records allocated on the stack
continuously
Large stack space required
57
Space for activation records are de-allocated, when the
termination condition of recursion is reached
Local
Variable
s
Return Value
Return Addr
58
Example:: main() calls fact(3)
int main()
{
int fact (int n)
int
{
if (n =
n; n
= 0)
= 3;
return (1);
printf (“%d \n”, fact(n) );
else
return 0;
return
}
(n *
fact(n-1)); 59
TRACE OF THE STACK DURING EXECUTION
n=0
1
RA .. fact fact
n=1 n=1 n=1 returns
main - - 1*1 = 1
to
RA .. fact RA .. fact RA .. fact
calls main
n=2 n=2 n=2 n=2 n=2
fact - - - - 2*1 = 2
RA .. fact RA .. fact RA .. fact RA .. fact RA .. fact
n=3 n=3 n=3 n=3 n=3 n=3 n=3
- - - - - - 3*2 = 6
RA .. main RA .. RA .. RA .. RA .. RA .. RA ..
main main main main main main
60
Do Yourself
Trace the activation records for the following
version of Fibonacci sequence
int f (int n)
{
int a, b; Local
if (n < return (n); Variable
2) else s (n, a,
b)
X {
a = f(n- Return Value
Y 1);
return (a+b); Return
} b = f(n- Addr (either
} 2); main, or X,
or Y)
void main() {
printf(“Fib(4) is: %d \n”, f(4));
main }
61
Additional Example
62
Towers of Hanoi Problem
1
2
3
4
5
64
Recursive statement of the general problem of n
disks
Step 1:
Move the top (n-1) disks from LEFT to CENTER
Step 2:
Move the largest disk from LEFT to RIGHT
Step 3:
Move the (n-1) disks from CENTER to RIGHT
65
Tower of Hanoi
A B C
66
Tower of Hanoi
A B C
67
Tower of Hanoi
A B C
68
Tower of Hanoi
A B C
69
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c &c \n”,
from, to) ; return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
…………………….
…………………….
}
70
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c &c \n”,
from, to) ; return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
printf (“Disk %d : %c %c\n”,
n, from, to) ;
……………………. 71
}
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c %c \n”, from, to) ;
return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
printf (“Disk %d : %c %c\n”, n, from, to) ;
towers (n-1, aux, to, from) ;
}
72
TOH runs
void towers(int n, char from, char to, char aux)
{ if (n==1) Output
{ printf ("Disk 1 : %c -> %c \n", from, to) ; 3
return ;
Disk 1 : A ->
}
C Disk 2 : A -
towers (n-1, from, aux, to) ;
> B Disk 1 : C
printf ("Disk %d : %c -> %c\n", n, from, to) ;
-> B Disk 3 :
towers (n-1, aux, to, from) ;
A -> C Disk
}
1 : B -> A
int main()
Disk 2 : B -> C
{ int n;
scanf("%d", &n); Disk 1 : A ->
towers(n,'A',‘C',‘B'); C
return 0;
} 58
More TOH runs 4
Output
void towers(int n, char from, char to, char aux) Disk 1 : A -> B
{ if (n==1) Disk 2 : A ->
{ printf ("Disk 1 : %c -> %c \n", C Disk 1 : B -
from, to) ; return ; > C Disk 3 : A
} -> B Disk 1 :
towers (n-1, from, aux, to) ; C -> A Disk
printf ("Disk %d : %c -> %c\n", n, from, to) ; 2 : C -> B
towers (n-1, aux, to, from) ; Disk 1 : A -> B
} Disk 4 : A ->
int main() C Disk 1 : B -
{ int n; > C Disk 2 : B
scanf("%d", &n); -> A Disk 1 :
towers(n,'A',‘C',‘B');
C -> A Disk
return 0;
3 : B -> C
}
Disk 1 : A -> B 59
Practice Problems
1. Write a recursive function to search for an element in an
array
2. Write a recursive function to count the digits of a positive
integer (do also for sum of digits)
3. Write a recursive function to reverse a null-terminated
string
4. Write a recursive function to convert a decimal number to
binary
5. Write a recursive function to check if a string is a
palindrome or not
6. Write a recursive function to copy one array to
another
Note: • For each of the above, write the main functions to call the
recursive function also
• Practice problems are just for practicing recursion, recursion is not
necessarily the most efficient way of doing them 60