0% found this document useful (0 votes)
17 views

Recursive Fns in C

Uploaded by

sachetan2005
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Recursive Fns in C

Uploaded by

sachetan2005
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 75

Recursion

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

 Used for repetitive computations in which each


action is stated in terms of a previous result
fact(n) = n * fact (n-1)

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

long int fact (int n)


{
if (n = = 1) return
(1); else return (n
* fact(n-1));
}
21
Factorial Execution
fact(4
)

long int fact (int n)


{
if (n = = 1) return
(1); else return (n
* fact(n-1));
}
22
Factorial Execution
fact(4)

if (4 = = 1) return
(1); else return
(4 * fact(3));

long int fact (int n)


{
if (n = = 1) return
(1); else return (n
* fact(n-1));
}
23
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 (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;

int fib (int n){


if (n == 0 or n == 1)
return 1; [Base]
return fib(n-2) + fib(n-1)
;
[Recurs
ive] 36
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 (3) fib (4)

fib (1) fib (2) fib (2) fib (3)

fib (0) fib (1) fib (0) fib (1) fib (1) fib (2)

fib (0) fib (1)

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 (3) fib (4)

fib (1) fib (2) fib (2) fib (3)


1

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 Fib (int, int); static int m1, m2;


int res, temp;
int main() if (i==2) {m1 =1; m2=1;}
{ if (n == i) res = m1+ m2;
int n; else
scanf("%d", &n); { temp = m1;
if (n == 0 || n ==1) m1 = m1+m2;
printf("F(%d) = %d \n", n, 1); m2 = temp;
else res = Fib(n, i+1);
printf("F(%d) = %d \n", n, }
Fib(n,2)); return res;
return 0; }
}
Static variables remain in existence rather than coming and going
each time a function is activated 33
Static Variables: See the addresses!
int Fib(int n, int i)
{ Output
static int m1, m2; 5
int res, temp; F: m1=1, m2=1, n=5, i=2
if (i==2) {m1 =1; m2=1;} F: &m1=134518656, &m2=134518660
printf("F: m1=%d, m2=%d, n=%d, F: &res=3221224516, &temp=3221224512
i=%d\n", m1,m2,n,i); F: m1=2, m2=1, n=5, i=3
printf("F: &m1=%u, &m2=%u\n", F: &m1=134518656, &m2=134518660
&m1,&m2); F: &res=3221224468, &temp=3221224464
printf("F: &res=%u, &temp=%u\n", F: m1=3, m2=2, n=5, i=4
&res,&temp); F: &m1=134518656, &m2=134518660
if (n == i) res = m1+ F: &res=3221224420, &temp=3221224416
m2; F: m1=5, m2=3, n=5, i=5
else { temp = m1; m1 = m1+m2; F: &m1=134518656, &m2=134518660
m2 = temp; F: &res=3221224372, &temp=3221224368
res = Fib(n, i+1); F(5) = 8
} return res;
}
34
Common Errors in Writing Recursive
Functions
 Non-terminating Recursive Function (Infinite recursion)
 No base case int badFactorial(int x)
{ return x * badFactorial(x-
1);
}
 The base case is never reached

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

 Two operations on stack, push and pop

 Whenever there is a function call, the activation


record gets pushed into the stack
 Activation record consists of the return address in
the calling program, the return value from the
function, and the local variables inside the function

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

Before call After call After return


55
int main()
{
…….. int ncr (int n, int r)
x = ncr (a, b); {
…….. return (fact(n)/ int fact (int n)
} fact(r)/fact(n- 3 times {
r)); ………
} return (result);
}

3 times

LV2, RV2, RA2

LV1, RV1, RA1 LV1, RV1, RA1 LV1, RV1, RA1

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

 We shall illustrate the process by an example of


computing factorial
 Activation record looks like:

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

LEFT CENTER RIGHT


63
 Initially all the disks are stacked on the LEFT pole
 Required to transfer all the disks to the RIGHT pole
 Only one disk can be moved at a time.
 A larger disk cannot be placed on a smaller disk
 CENTER pole is used for temporary storage of disks

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

You might also like