0% found this document useful (0 votes)
11 views93 pages

12 2Recursion Final

Recursion is a process where a procedure calls itself, potentially infinitely, and is used in programming to solve large problems by breaking them down into smaller, simpler problems. Examples include counting down from a number and calculating factorials, both of which can be implemented iteratively or recursively. It is essential to have a terminating condition to prevent infinite recursion.

Uploaded by

Santosh Deshmukh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views93 pages

12 2Recursion Final

Recursion is a process where a procedure calls itself, potentially infinitely, and is used in programming to solve large problems by breaking them down into smaller, simpler problems. Examples include counting down from a number and calculating factorials, both of which can be implemented iteratively or recursively. It is essential to have a terminating condition to prevent infinite recursion.

Uploaded by

Santosh Deshmukh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 93

Recursion

Kumkum Saxena
Recursion
◼ What is Recursion?
◼ In plain English:
◼ Recursion: the process a procedure goes through,
when one of the steps of the procedure involves
rerunning the entire procedure
▪ Example: say that some procedure has 4 steps
▪ The 3rd step instructs you to run the entire procedure again
▪ Each time you get to the third step, you have to start anew
▪ This goes on, potentially, infinitely
▪ And this is an example of Recursion

Kumkum Saxena Recursion page 2


Recursion:
Ex of Thinking Recursively
Strategy for processing nested dolls:
INITIATE FUNCTION “Open All Dolls”
if there is only one doll
(1) you’re done! Play with the doll.
else
(1) open the outer doll
(2) Process the inner nest in the same way
This part is the “recursion”

Kumkum Saxena Recursion page 3


Recursion
◼ What is Recursion?
◼ From the programming perspective:
◼ A recursive function is one that contains a call to its
own self
◼ Example: we know that we are allowed to call function
B from within function A
◼ Also, you are allowed to call function A from within
function A!
▪ This is recursion

◼ Note:
◼ This could go on for infinity as function A keeps calling
function A
▪ So we must have a way to exit the function!
Kumkum Saxena Recursion page 4
Recursion Example w/o terminate
◼ Example of recursion without a terminating
condition. Just keeps going and going and…
#include <stdio.h>

void print(); // This is just a cheesy function that prints something

int main() {
print(); // Here we call the cheesy function
system("PAUSE");

return 0;
}

void print() {

printf(“Example of recursion WITHOUT a stopping case.\n");


print(); // And here is the recursive function call
}

Kumkum Saxena Recursion page 5


Recursion
◼ What is Recursion?
◼ From the programming perspective:
◼ Recursion solves large problems by reducing
them to smaller problems of the same form
◼ Again, recursion is a function that invokes itself
◼ Basically splits a problem into one or more SIMPLER
versions of itself
◼ And we must have a way of stopping the recursion
◼ So the function must have some sort of calls or
conditional statements that can actually terminate the
function

Kumkum Saxena Recursion page 6


Recursion
◼ Programming example:
◼ Let us write a program that counts down from 10
and then prints BLAST OFF!
◼ How would we do this iteratively?
#include <stdio.h>

int main(void) {
int i;
for (i = 10; i > 0; --i)
printf(“%d! ”, i);
printf(“\nBLAST OFF!\n”);
}

◼ This program prints:


◼ 10! 9! 8! 7! 6! 5! 4! 3! 2! 1!
BLAST OFF!
Kumkum Saxena Recursion page 7
Recursion
◼ How do we do this recursively?
◼ We need a function that we will call
◼ And this function will then call itself
▪ until the stopping case
#include <stdio.h> Here’s the Count Down Function
void count_down(int n){
void count_down(int n); if (n>0) {
printf(“%d! ”, i);
int main(void) { count_down(n-1);
count_down(10); }
return 0; else
} printf(“\nBLAST OFF!\n”);
}
◼ Once again, this program prints:
◼ 10! 9! 8! 7! 6! 5! 4! 3! 2! 1!
BLAST OFF!

Kumkum Saxena Recursion page 8


Recursion
◼ Program Details:
◼ So what’s going on here in this program?
◼ The first line of the main program calls the function

count_down, with 10 as the input


▪ Think of this as starting a new “mini” program
◼ When count_down(10) runs, what happens?
▪ Execution flows into the first IF statement
▪ Cause 10 is surely greater than 0.
▪ After printing “10!”, the function count_down then CALLS
ITSELF with count_down(9)
▪ Think of this as starting another “mini” program
▪ Again, execution flows into the first IF statement
▪ Cause 9 is surely greater than 0.
▪ This new, mini program then prints “9!” and calls itself with
count_down(8)
Kumkum Saxena Recursion page 9
Recursion
◼ Program Details:
◼ So what’s going on here in this program?
◼ This continues until we get to the mini program called

count_down(1)
▪ This mini program will print “1!”
▪ Cuz, again, 1 is greater than 0
▪ And then it calls count_down(0)
◼ What happens now?
▪ Execution does NOT flow into the IF statement
▪ 0 is NOT greater than 0
▪ So execution goes into the ELSE statement
▪ BLAST OFF! is printed
▪ This mini program has finished
▪ AND all the other function calls have finished
▪ Control returns to the main program and the program ends.
Kumkum Saxena Recursion page 10
Recursion
◼ Here’s what’s going on…in pictures
#include <stdio.h> count_down(10) Think of this as
Prints 10!
count_down(9)
calls count_down(9) your function stack
void count_down(int n); Prints 9!
callscount_down(8)
count_down(8)
Prints 8!
int main(void) { callscount_down(7)
count_down(7)
Prints 7!
count_down(10); callscount_down(6)
count_down(6)
Prints 6!
return 0; callscount_down(5)
count_down(5)
} Prints 5!
callscount_down(4)
count_down(4)
Prints 4!
callscount_down(3)
count_down(3)
Prints 3!
callscount_down(2)
count_down(2)
Prints 2!
callscount_down(1)
count_down(1)
Prints 1!
count_down(0)
calls count_down(0)
◼ The Output: Prints BLAST OFF!
◼ 10! 9! 8! 7! 6! 5! 4! 3! 2! 1!
BLAST OFF!

Kumkum Saxena Recursion page 11


Recursion - Factorial
◼ Count Down program
◼ Not the most enlightening
◼ But it gives us an idea of how recursion works
◼ Let’s look at another example

◼ Example: Compute Factorial of a Number


◼ What is a factorial?
◼ 4! = 4 * 3 * 2 * 1 = 24
◼ In general, we can say:
◼ n! = n * (n-1) * (n-2) * … * 2 * 1
◼ Also, 0! = 1

Kumkum Saxena Recursion page 12


Recursion - Factorial
◼ Example: Compute Factorial of a Number
◼ Typical iterative solution

int fact(int n)
{ Straightforward Result:
int p, j; ex: n=3
p = 1;
for ( j=n; j>=1; j--) p = 1*3 // p = 3
p = p* j; p = 3*2 // p = 6
return ( p ); p = 6*1 // p = 6
}

Kumkum Saxena Recursion page 13


Recursion - Factorial
◼ Example: Compute Factorial of a Number
◼ Recursive Solution
◼ How do we come up with a recursive solution to

this?
▪ This is really the hardest part
◼ You MUST figure out how you can think of the
problem in a recursive manner.
▪ Ask yourself: how can we rewrite this problem so
that it is defined recursively?
◼ Remember, we said that recursion:
▪ solves large problems by reducing them to
smaller problems of the same form
Kumkum Saxena Recursion page 14
Recursion - Factorial
◼ Example: Compute Factorial of a Number
◼ Recursive Solution
◼ Mathematically, factorial is already defined recursively
▪ Note that each factorial is related to a factorial of the
next smaller integer
◼ 4! = 4*3*2*1 = 4 * (4-1)! = 4 * (3!)
◼ Right?
◼ Another example:
◼ 10! = 10*9*8*7*6*5*4*3*2*1
This is clear right?
◼ 10! = 10*(9!) Since 9! clearly is equal to
9*8*7*6*5*4*3*2*1

Kumkum Saxena Recursion page 15


Recursion - Factorial
◼ Example: Compute Factorial of a Number
◼ Recursive Solution
◼ Mathematically, factorial is already defined recursively
▪ Note that each factorial is related to a factorial of the
next smaller integer
◼ Now we can say, in general, that:
◼ n! = n * (n-1)!
◼ But we need something else
▪ We need a stopping case, or this will just go on and on and on
▪ NOT good!
◼ So in “math terms”, we say
◼ We let 0! = 1
▪ n! = 1 if n = 0
▪ n! = n * (n-1)! if n > 0

Kumkum Saxena Recursion page 16


Recursion - Factorial
◼ How do we do this recursively?
◼ We need a function that we will call
◼ And this function will then call itself (recursively)
▪ until the stopping case (n = 0)
#include <stdio.h> Here’s the Fact Function
int Fact (int n) {
int Fact(int n); if (n == 0)
int main(void) { return 1;
int factorial = Fact(10); else
printf(“%d\n”, factorial); return (n * fact(n-1));
return 0; }
}

◼ This program prints the result of 10*9*8*7*6*5*4*3*2*1:


▪ 3628800
Kumkum Saxena Recursion page 17
© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 18

Winding and Unwinding phase

Winding phase
Invoking/calling ‘itself’ to solve
smaller or simpler instance(s) of
a problem …
… and then building up the
answer(s) of the simpler
instance(s).
Unwinding phase

Kumkum Saxena Recursion page 18


Recursion - Factorial
◼ Here’s what’s going on…in pictures
#include <stdio.h> Fact(10)
Returns (10*Fact(9))
Fact(9)
int Fact(int n); Returns (9*Fact(8))
Fact(8)
int main(void) { Returns (8*Fact(7))
Fact(7)
int factorial = Fact(10); Returns (7*Fact(6))
printf(“%d\n”, factorial); Fact(6)
Returns (6*Fact(5))
return 0; Fact(5)
} Returns (5*Fact(4))
Fact(4)
Returns (4*Fact(3))
Fact(3)
Returns (3*Fact(2))
Fact(2)
Returns (2*Fact(1))
Fact(1)
Returns (1*Fact(0))
Fact(0)
Returns 1

Kumkum Saxena Recursion page 19


Recursion - Factorial
◼ Here’s what’s going on…in pictures
#include <stdio.h> Fact(10)
Returns (10*Fact(9))
Fact(9)
int Fact(int n); Returns (9*Fact(8))
Fact(8)
int main(void) { Returns (8*Fact(7))
Fact(7)
int factorial = Fact(10); Returns (7*Fact(6))
printf(“%d\n”, factorial); Fact(6)
Returns (6*Fact(5))
return 0; Fact(5)
} Returns (5*Fact(4))
Fact(4)
Returns (4*Fact(3))
Fact(3)
Returns (3*Fact(2))
Fact(2)
Returns (2*Fact(1))
◼ So now when we return, Fact(1)
Returns (1*Fact(0))
◼ Where do we return to? Fact(0)
Returns 1
◼ We return to the function that called Fact(0)
◼ We return the value, 1, into the spot that called Fact(0)
Kumkum Saxena Recursion page 20
Recursion - Factorial
3628800

◼ Here’s what’s going on…in pictures


#include <stdio.h> Fact(10)
Returns (10*362880)
(10*Fact(9))
Fact(9)
void Fact(int n); 362880 Returns (9*40320)
(9*Fact(8))
Fact(8)
int main(void) { 40320 Returns (8*5040)
(8*Fact(7))
Fact(7)
int factorial = Fact(10); 5040 Returns (7*720)
(7*Fact(6))
printf(“%d\n”, factorial); Fact(6)
720 Returns (6*120)
(6*Fact(5))
return 0; Fact(5)
} 120 Returns (5*24)
(5*Fact(4))
Fact(4)
24 Returns (4*6)
(4*Fact(3))
Fact(3)
6 Returns (3*2)
(3*Fact(2))
Fact(2)
2 Returns (2*1)
(2*Fact(1))
Fact(1)
◼ Now factorial has the value 3,628,800. 1 (1*1)
Returns (1*Fact(0))
Fact(0)
1 Returns 1

Kumkum Saxena Recursion page 21


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 22

2.1 Demo #1: Factorial (3/3)


int f(int n) {
if (n == 0)
▪ Trace factorial(3). For simplicity, we return 1;
else
write f(3). return n * f(n-1);
Winding: }
Trace tree:
f(3): Since 3 ≠ 0, call 3 * f(2)
f(3) 6
f(2): Since 2 ≠ 0, call 2 * f(1)
f(1): Since 1 ≠ 0, call 1 * f(0)
3 * f(2) 2
f(0): Since 0 == 0, …

Unwinding: 2 * f(1) 1
f(0): Return 1
1 * f(0) 1
f(1): Return 1 * f(0) = 1 * 1 = 1
f(2): Return 2 * f(1) = 2 * 1 = 2
f(3): Return 3 * f(2) = 3 * 2 = 6

Kumkum Saxena Recursion page 22


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 23

2.2 Demo #2: Fibonacci (1/4)


▪ The Fibonacci series models the rabbit
population each time they mate:
1, 1, 2, 3, 5, 8, 13, 21, …

▪ The modern version is:


0, 1, 1, 2, 3, 5, 8, 13, 21, …

▪ Fibonacci numbers are found


in nature (sea-shells,
sunflowers, etc)
▪ http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibnat.html

Kumkum Saxena Recursion page 23


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 24

2.2 Demo #2: Fibonacci (2/4)


▪ Fibonacci numbers are found in nature (sea-shells,
sunflowers, etc)
▪ http://www.maths.surrey.ac.uk/hosted-
sites/R.Knott/Fibonacci/fibnat.html

Kumkum Saxena Recursion page 24


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 25

2.2 Demo #2: Fibonacci (3/4)


0, 1, 1, 2, 3, 5, 8, 13, 21, … Unit17_Fibonacci.c

Iterative code: Recursive code:


// Pre-cond: n >= 0 // Pre-cond: n >= 0
int fib_iter(int n) { int fib(int n) {
int prev1 = 1, if (n < 2)
prev2 = 0, sum; return n;
else
if (n < 2) return fib(n-1) + fib(n-2);
return n; }
for (; n>1; n--) {
sum = prev1 + prev2; Recurrence relation:
prev2 = prev1; fn = fn-1 + fn-2 n ≥ 2
prev1 = sum; f0 = 0
} f1 = 1
return sum;
}

Kumkum Saxena Recursion page 25


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 26
int fib(int n) {
if (n < 2)
return n;
2.2 Fibonacci (4/4) else
return fib(n-1) + fib(n-2);
}

▪ fib(n) makes 2 recursive calls: fib(n-1) and fib(n-2)


Winding
▪ Trace tree (or call tree) for fib(5)
5 Unwinding

fib(5)
3 2

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

1 1 1 0 1 0

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

1 0

fib(1) fib(0)

Kumkum Saxena Recursion page 26


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 27

3. Gist of Recursion (1/6)


Iteration vs Recursion: How to compute factorial(3)?
You, do f(2) for me.
Recursion man
I’ll return 3 * your
answer to my boss.
You, do f(1) for me.
Iteration man I’ll return 2 * your
answer to my boss.
I do f(3) all by f(3) You, do f(0) for me.
myself…return I’ll return 1 * your
6 to my boss. answer to my boss.
f(2)
I will do f(0) all by
myself, and return
1 to my boss.
f(3) f(1)

f(0)

Kumkum Saxena Recursion page 27


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 28

3. Gist of Recursion (2/6)

▪ Problems that lend themselves to a recursive solution


have the following characteristics:
▪ One or more simple cases (also called base cases or anchor
cases) of the problem have a straightforward, non-recursive
solution
▪ The other cases can be redefined in terms of problems that are
smaller, i.e. closer to the simple cases
▪ By applying this redefinition process every time the recursive
function is called, eventually the problem is reduced entirely to
simple cases, which are relatively easy to solve
▪ The solutions of the smaller problems are combined to obtain the
solution of the original problem

Kumkum Saxena Recursion page 28


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 29

3. Gist of Recursion (3/6)


▪ To write a recursive function:
▪ Identify the base case(s) of the relation
▪ Identify the recurrence relation
// Pre-cond: n >= 0 // Pre-cond: n >= 0
int factorial(int n) { int fib(int n) {
if (n == 0) if (n < 2)
return 1; return n;

else else
return n * factorial(n-1); return fib(n-1) + fib(n-2);
} }

Kumkum Saxena Recursion page 29


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 30

3. Gist of Recursion (4/6)

▪ Always check for base case(s) first


▪ What if you omit base case(s)?
▪ Do not write redundant base cases
int factorial(int n) {
if (n == 0)
return 1;
else if (n == 1)
return 1; redundant
else if (n == 2)
return 2;
else if (n == 3)
return 6;
else
return n * factorial(n-1);
}

Kumkum Saxena Recursion page 30


© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 31

3. Gist of Recursion (5/6)

▪ When a function is called, an activation record (or


frame) is created by the system.
▪ Each activation record stores the local parameters
and variables of the function and its return address.
▪ Such records reside in the memory called stack.
▪ Stack is also known as LIFO (last-in-first-out) structure
▪ A recursive function can potentially create many
activation records
▪ Winding: each recursive call creates a separate record
▪ Unwinding: each return to the caller erases its
associated record
Kumkum Saxena Recursion page 31
© NUS CS1010 (AY2014/5 Semester 1) Unit17 - 32
int f(int n) {
if (n == 0) return 1;
3. Gist of Recursion (6/6) }
else return n * f(n-1);

▪ Example: factorial(3) n
0
n n 1 n
1 1 1
n n n n 1
2 2 2 2
n n n n n
3 3 3 3 3

f(3) f(2) f(1) f(0) n


2
2
n n
3 3
6

Kumkum Saxena Recursion page 32


Recursion
◼ Recursive functions
◼ Are functions that calls themselves
◼ Can only solve a base case
◼ If not base case, the function breaks the
problem into a slightly smaller, slightly simpler,
problem that resembles the original problem and
◼ Launches a new copy of itself to work on the smaller
problem, slowly converging towards the base case
◼ When computing a value, often makes a call to itself
inside the return statement
◼ Eventually the base case gets solved and then that
value works its way back up to solve the whole
problem
Kumkum Saxena Recursion page 33
Recursion
◼ So why use recursion?
◼ Elegant solution to complex problems
◼ Some solutions are naturally recursive
◼ Sometimes these involve writing less code and
are clearer to read

Kumkum Saxena Recursion page 34


Recursion
◼ On the flipside, why NOT use recursion…
◼ Every problem that can be solved recursively
can be solved with iteration.
◼ Recursive calls take up both memory and CPU
time
◼ Exponential Complexity – calling the Fib function uses
2n function calls.
◼ Trade off of High Performance vs. Good
Software Engineering.

Kumkum Saxena Recursion page 35


Recursion - Fibonacci
◼ Fibonacci Sequence
◼ Some programs are just more naturally written recursively
◼ Fibonacci is one such example
◼ What is the Fibonacci sequence?
◼ The first two terms of the sequence are 1
◼ Each of the following terms is the sum of the two previous terms
▪ 1 1 2 3 5 8 13 21 34 55 89 144 …

◼ So how can we define this Fibonacci sequence:


◼ Base (stopping) cases:
fib(1) = 1
fib(2) = 1
◼ fib(n) = fib(n-1) + fib(n-2), for n > 2
▪ So, fib(7), referring to the seventh Fibonacci number, which we see from the
sequence above is 13, can be found by adding fib(6) + fib(5).

Kumkum Saxena Recursion page 36


Recursion - Fibonacci
◼ So how do we code this up recursively?
◼ We need a function that we will call
◼ And this function will then call itself
▪ until the stopping cases (n = 1 or n = 2)
#include <stdio.h> Here’s the fib function
int fib(int n) {
int fib(int n); if (n <= 2)
int main(void) { return 1;
int FibNum= fib(10); else
printf(“%d\n”, FibNum); return fib(n-1) + fib(n-2);
return 0; }
}

◼ This program prints out the 10th fibonacci number:


▪ 55
Kumkum Saxena Recursion page 37
Recursion - Fibonacci
◼ Fibonacci Sequence:
◼ So what was the point of this example?
◼ Showed how recursive programming can truly be
easier
◼ h(x,i)=( x mod
Recursive m +i)modare
solutions m often more elegant
▪ Although not necessarily faster
◼ And recursive solutions are often the obvious choice
based on the given function definitions

Kumkum Saxena Recursion page 38


More Recursion

Kumkum Saxena
Recursion
◼ What is Recursion? From the programming
perspective:
◼ Recursion solves large problems by reducing
them to smaller problems of the same form
◼ Recursion is a function that invokes itself
◼ Basically splits a problem into one or more SIMPLER
versions of itself
◼ And we must have a way of stopping the recursion
◼ So the function must have some sort of calls or
conditional statements that can actually terminate the
function

Kumkum Saxena Recursion page 40


Recursion: General Structure
◼ General Structure of Recursive Functions:
◼ Basic structure has 2 main options:
1) Break down the problem further
◼ Into a smaller sub-problem
2) OR, the problem is small enough on its own
◼ Solve it

◼ In programming, when we have two options, we


us an if statement

◼ So here are our two constructs of recursive


functions…
Kumkum Saxena Recursion page 41
Recursion: General Structure
◼ General Structure of Recursive Functions:
◼ 2 general constructs:
◼ Construct 1:

if (terminating condition) {
DO FINAL ACTION
}
else {
Take one step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

◼ Functions that return values take on this construct


Kumkum Saxena Recursion page 42
Recursion: General Structure
◼ General Structure of Recursive Functions:
◼ 2 general constructs:
◼ Construct 2:

if (!(terminating condition) ) {
Take a step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

◼ void recursive functions use this construct


Kumkum Saxena Recursion page 43
Recursion: General Structure
◼ Example using Construct 1
◼ Our function (Sum Integers):
◼ Takes in one positive integer parameter, n
◼ Returns the sum 1+2+…+n
◼ So our recursive function must sum all the integers up
until (and including) n
◼ How do we do this recursively?
◼ We need to solve this in such a way that part of the
solution is a sub-problem of the EXACT same nature of
the original problem.

Kumkum Saxena Recursion page 44


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we define the following function
▪ f(n) = 1 + 2 + 3 + … + n
▪ Hopefully it is clear that this is our desired function
▪ Example:
▪ f(10) = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10

◼ So the question is:


◼ Given this function, f(n), how do we make it
recursive???
Kumkum Saxena Recursion page 45
Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we define the following function
▪ f(n) = 1 + 2 + 3 + … + n

◼ REMEMBER:
◼ We want a function that solves this same problem
◼ But we want that problem to be recursive:
▪ It should solve f(n) by reducing it to a smaller problem, but of
the same form
◼ Just like the factorial example: n! = n * (n-1)!
▪ (n-1)! was a smaller form of n!
◼ So think, what is a “smaller form” of our function, f(n)
Kumkum Saxena Recursion page 46
Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we define the following function
▪ f(n) = 1 + 2 + 3 + … + n

◼ So to make this recursive, can we say:


▪ f(n) = 1 + (2 + 3 + … + n)
◼ Does that “look” recursive?
◼ Is there a sub-problem that is the EXACT same form as
the original problem?
▪ NO!
◼ 2+3+…+n is NOT a sub-problem of the form 1+2+…+n

Kumkum Saxena Recursion page 47


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we get the following function
▪ f(n) = 1 + 2 + 3 + … + n
◼ Let’s now try this:
▪ f(n) = 1 + 2 + … + n = n + (1 + 2 + … + (n-1))
◼ Here we have an expression
▪ 1 + 2 + … + (n-1)
◼ which IS indeed a sub-problem of the same form

Kumkum Saxena Recursion page 48


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we get the following function
▪ f(n) = 1 + 2 + 3 + … + n
◼ So now we have:
▪ f(n) = 1 + 2 + … + n = n + (1 + 2 + … + (n-1))
◼ Now, realize the following:
▪ Use an example:
▪ f(10) = 1 + 2 + … + 10 = 10 + (1 + 2 + … + 9)
▪ And what is (1 + 2 + … + 9)? It is f(9)!
▪ So look at what we can say:
▪ We can say that, f(10) = 10 + f(9)

Kumkum Saxena Recursion page 49


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we get the following function
▪ f(n) = 1 + 2 + 3 + … + n
◼ So now we have:
▪ f(n) = 1 + 2 + … + n = n + (1 + 2 + … + (n-1))
◼ Now, realize the following:
▪ So, in general, we have: f(n) = n + f(n-1)
▪ Right?
▪ Just like f(10) = 10 + f(9)
▪ So, we’ve defined our function, f(n), to be in terms of
a smaller version of itself…in terms of f(n-1)

Kumkum Saxena Recursion page 50


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ Using n as the input, we get the following function
▪ f(n) = 1 + 2 + 3 + … + n
◼ So now we have:
▪ f(n) = 1 + 2 + … + n = n + (1 + 2 + … + (n-1))
◼ Now, realize the following:
▪ So here is our function, defined recursively
▪ f(n) = n + f(n-1)

Kumkum Saxena Recursion page 51


Recursion: General Structure
◼ Example using Construct 1
◼ Our function (now recursive):
◼ f(n) = n + f(n-1)
◼ Reminder of construct 1:

if (terminating condition) {
DO FINAL ACTION
}
else {
Take one step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

Kumkum Saxena Recursion page 52


Recursion: General Structure
◼ Example using Construct 1
◼ Our function:
◼ f(n) = n + f(n-1)
◼ Reminder of construct 1:
◼ So we need to determine the terminating condition!
◼ We know that f(0) = 0
▪ So our terminating condition can be n = 0
◼ Additionally, our recursive calls need to return an
expression for f(n) in terms of f(k)
▪ for some k < n
◼ We just found that f(n) = n + f(n-1)
◼ So now we can write our actual function…
Kumkum Saxena Recursion page 53
Recursion: General Structure
◼ Example using Construct 1
◼ Our function: f(n) = n + f(n-1)

// Pre-condition: n is a positive integer.


// Post-condition: Function returns the sum
// 1 + 2 + ... + n
int sumNumbers(int n) {

if ( n == 0 )
return 0;
else
return (n + sumNumbers(n-1));
}

Kumkum Saxena Recursion page 54


Recursion: General Structure
◼ Another example using Construct 1
◼ Our function:
◼ Calculates be
▪ Some base raised to a power, e
▪ The input is the base, b, and the exponent, e
▪ So if the input was 2 for the base and 4 for the exponent
▪ The answer would be 24 = 16
◼ How do we do this recursively?
◼ We need to solve this in such a way that part of the
solution is a sub-problem of the EXACT same nature of
the original problem.

Kumkum Saxena Recursion page 55


Recursion: General Structure
◼ Another example using Construct 1
◼ Our function:
◼ Using b and e as input, here is our function
▪ f(b,e) = be
◼ So to make this recursive, can we say:
▪ f(b,e) = be = b*b(e-1) Example with numbers:
◼ Does that “look” recursive? f(2,4) = 24 = 2*23
---So we solve the larger
◼ YES it does! problem (24) by reducing it to
◼ Why? a smaller problem (23).
◼ Cuz the right side is indeed a sub-problem of the original
◼ We want to evaluate be
◼ And our right side evaluates b(e-1)
Kumkum Saxena Recursion page 56
Recursion: General Structure
◼ Another example using Construct 1
◼ Our function:
◼ f(b,e) = b*b(e-1)
◼ Reminder of construct 1:

if (terminating condition) {
DO FINAL ACTION
}
else {
Take one step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

Kumkum Saxena Recursion page 57


Recursion: General Structure
◼ Another example using Construct 1
◼ Our function:
◼ f(b,e) = b*b(e-1)
◼ Reminder of construct 1:
◼ So we need to determine the terminating condition!
◼ We know that f(b,0) = b0 = 1
▪ So our terminating condition can be when e = 0
◼ Additionally, our recursive calls need to return an
expression for f(b,e) in terms of f(b,k)
▪ for some k < e
◼ We just found that f(b,e) = b*b(e-1)
◼ So now we can write our actual function…
Kumkum Saxena Recursion page 58
Recursion: General Structure
◼ Another example using Construct 1
◼ Our function:

// Pre-conditions: e is greater than or equal to 0.


// Post-conditions: returns be.
int Power(int base, int exponent) {

if ( exponent == 0 )
return 1;
else
return (base*Power(base, exponent-1));
}

Kumkum Saxena Recursion page 59


Recursion: General Structure
◼ Example using Construct 2
◼ Remember the construct:
◼ This is used when the return type is void

if (!(terminating condition) ) {
Take a step closer to terminating condition
Call function RECURSIVELY on smaller subproblem
}

Kumkum Saxena Recursion page 60


Recursion: General Structure
◼ Example using Construct 2
◼ Our function:
◼ Takes in a string (character array)
◼ Also takes in an integer, the length of the string
◼ The function simply prints the string in REVERSE order
◼ So what is the terminating condition?
◼ We will print the string, in reverse order, character by
character
◼ So we terminate when there are no more characters left
to print
◼ The 2nd argument to the function (length) will be reduced
until it is 0 (showing no more characters left to print)
Kumkum Saxena Recursion page 61
Recursion: General Structure
◼ Example using Construct 2
◼ Our function:
void printReverse(char word[], int length) {
if (length > 0) {
printf(“%c”, word[length-1]);
printReverse(word, length-1);
}
}

◼ What’s going on:


◼ Let’s say the word is “computer”
▪ 8 characters long
◼ So we print word[7]
▪ Which would refer to the “r” in computer
Kumkum Saxena Recursion page 62
Recursion: General Structure
◼ Example using Construct 2
◼ Our function:
void printReverse(char word[], int length) {
if (length > 0) {
printf(“%c”, word[length-1]);
printReverse(word, length-1);
}
}

◼ What’s going on:


◼ We then recursively call the function
◼ Sending over two arguments:
▪ The string, “computer”
▪ And the length, minus 1
Kumkum Saxena Recursion page 63
Recursion: General Structure
◼ Example using Construct 2
◼ Our function:
void printReverse(char word[], int length) {
if (length > 0) {
printf(“%c”, word[length-1]);
printReverse(word, length-1);
}
}

◼ What’s going on:


◼ After the first recursive call, length is now 7
◼ Therefore, word[6] is printed
▪ Referring to the “e” in computer
◼ Then we recurse (again and again) and finish once length <= 0
Kumkum Saxena Recursion page 64
Recursion – Practice Problem
◼ Practice Problem:
◼ Write a recursive function that:
◼ Takes in two non-negative integer parameters
◼ Returns the product of these parameters
▪ But it does NOT use multiplication to get the answer
◼ So if the parameters are 6 and 4
◼ The answer would be 24

◼ How do we do this not actually using multiplication


◼ What another way of saying 6*4?
◼ We are adding 6, 4 times!
◼ 6*4 = 6 + 6 + 6 + 6
◼ So now think of your function…
Kumkum Saxena Recursion page 65
Recursion – Practice Problem
◼ Practice Problem:
◼ Solution:

// Precondition: Both parameters are


// non-negative integers.
// Postcondition: The product of the two
// parameters is returned.
function Multiply(int first, int second) {
if (( second == 0 ) || ( first = 0 ))
return 0;
else
return (first + Multiply(first, second-1));
}

Kumkum Saxena Recursion page 66


Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Here’s the problem:
◼ There are three vertical poles
◼ There are 64 disks on tower 1 (left most tower)
▪ The disks are arranged with the largest diameter disks at
the bottom
◼ Some monk has the daunting task of moving disks
from one tower to another tower
▪ Often defined as moving from Tower #1 to Tower #3
▪ Tower #2 is just an intermediate pole
▪ He can only move ONE disk at a time
▪ And he MUST follow the rule of NEVER putting a bigger
disk on top of a smaller disk

Kumkum Saxena Recursion page 67


Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
◼ We must find a recursive strategy
◼ Thoughts:
▪ Any tower with more than one disk must clearly be moved
in pieces
▪ If there is just one disk on a pole, then we move it

start temp finish


Kumkum Saxena Recursion page 68
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
◼ Irrespective of the number of disks, the following steps
MUST be carried out:
▪ The bottom disk needs to move to the destination tower
1) So step 1 must be to move all disks above the bottom
disk to the intermediate tower
2) In step 2, the bottom disk can now be moved to the
destination tower
3) In step 3, the disks that were initially above the bottom
disk must now be put back on top
▪ Of course, at the destination

◼ Let’s look at the situation with only 3 disks…


Kumkum Saxena Recursion page 69
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
◼ Step 1:
▪ Move 2 disks from start to temp using finish Tower.
▪ To understand the recursive routine, let us assume that we
know how to solve 2 disk problem, and go for the next
step.
▪ Meaning, we “know” how to move 2 disks appropriately

start temp finish start temp finish


Kumkum Saxena Recursion page 70
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
◼ Step 2:
▪ Move the (remaining) single disk from start to finish
▪ This does not involve recursion
▪ and can be carried out without using temp tower.
▪ In our program, this is just a print statement
▪ Showing what we moved and to where

start temp finish start temp finish


Kumkum Saxena Recursion page 71
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
◼ Step 3:
▪ Now we are at the last step of the routine.
▪ Move the 2 disks from temp tower to finish tower using the
start tower
▪ This is also done recursively

start temp finish start temp finish


Kumkum Saxena Recursion page 72
Recursion – Towers of Hanoi

start 1

start temp finish start temp finish

2 3

start temp finish start temp finish

start temp finish


Kumkum Saxena Recursion page 73
Recursion – Towers of Hanoi
5

start temp finish start temp finish

start temp finish


◼ # of steps needed:
◼ We had 3 disks requiring seven steps
◼ 4 disks would require 15 steps
◼ n disks would require 2n -1 steps
◼ HUGE number
Kumkum Saxena Recursion page 74
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
// Function Prototype
void moveDisks(int n, char start, char finish, char temp);

void main() {
int disk;
int moves;
printf("Enter the # of disks you want to play with:");
scanf("%d",&disk);
// Print out the # of moves required
moves = pow(2,disk)-1;
printf("\nThe No of moves required is=%d \n",moves);
// Initiate the recursion
moveDisks(disk,'A','C','B');
}
Kumkum Saxena Recursion page 75
Recursion – Towers of Hanoi
◼ Towers of Hanoi:
◼ Solution:
void moveDisks(int n, char start, char finish, char temp) {
if (n == 1) {
printf(“Move Disk from %c to %c\n”, start, finish);
}
else {
moveDisks(n-1, start, temp, finish);
printf(“Move Disk from %c to %c\n”, start, finish);
moveDisks(n-1, temp, finish, start);
}
}

Kumkum Saxena Recursion page 76


And More
Recursion

Kumkum Saxena
Binary Search
◼ Array Search
◼ We are given the following sorted array:
index 0 1 2 3 4 5 6 7 8
value 2 6 19 27 33 37 38 41 118

◼ We are searching for the value, 19 (for example)


◼ Remember, we said that you search the middle
element
◼ If found, you are done
◼ If the element in the middle is greater than 19
▪ Search to the LEFT (cuz 19 MUST be to the left)
◼ If the element in the middle is less than 19
▪ Search to the RIGHT (cuz 19 MUST then be to the right)
Kumkum Saxena Recursion page 78
Binary Search
◼ Array Search
◼ We are given the following sorted array:
index 0 1 2 3 4 5 6 7 8
value 2 6 19 27 33 37 38 41 118

◼ We are searching for the value, 19


◼ So, we MUST start the search in the middle
INDEX of the array.
◼ In this case:
◼ The lowest index is 0
◼ The highest index is 8
◼ So the middle index is 4
Kumkum Saxena Recursion page 79
Binary Search
◼ Array Search
◼ Correct Strategy
◼ We would ask, “is the number I am searching for, 19,
greater or less than the number stored in index 4?
▪ Index 4 stores 33
◼ The answer would be “less than”
◼ So we would modify our search range to in between
index 0 and index 3
▪ Note that index 4 is no longer in the search space
◼ We then continue this process
▪ The second index we’d look at is index 1, since (0+3)/2=1
▪ Then we’d finally get to index 2, since (2+3)/2 = 2
▪ And at index 2, we would find the value, 19, in the array
Kumkum Saxena Recursion page 80
Binary Search
◼ Binary Search code:
int binsearch(int a[], int len, int value) {

int low = 0, high = len-1;


while (low <= high) {
int mid = (low+high)/2;
if (value < a[mid])
high = mid-1;
else if (value > a[mid])
low = mid+1;
else
return 1;
}

return 0;
}
Kumkum Saxena Recursion page 81
Binary Search
◼ Binary Search code:
◼ At the end of each array iteration, all we do is
update either low or high
◼ This modifies our search region
◼ Essentially halving it
◼ As we saw previously, this runs in log n time

◼ But this iterative code isn’t the easiest to read


◼ We now look at the recursive code
◼ MUCH easier to read and understand

Kumkum Saxena Recursion page 82


Binary Search – Recursive
◼ Binary Search using recursion:
◼ We need a stopping case:
◼ We need to STOP the recursion at some point

◼ So when do we stop:
1) When the number is found!
2) Or when the search range is nothing
◼ huh?
◼ The search range is empty when (low > high)

◼ So how let us look at the code…


Kumkum Saxena Recursion page 83
Binary Search – Recursive
◼ Binary Search Code (using recursion):
◼ We see how this code follows from the
explanation of binary search quite easily
int binSearch(int *values, int low, int high, int searchval)
int mid;
if (low <= high) {
mid = (low+high)/2;
if (searchval < values[mid])
return binSearch(values, low, mid-1, searchval);
else if (searchval > values[mid])
return binSearch(values, mid+1, high, searchval);
else
return 1;
}
return 0;
}
Kumkum Saxena Recursion page 84
Binary Search – Recursive
◼ Binary Search Code (using recursion):
◼ So if the value is found
◼ We return 1
◼ Otherwise,
◼ if (searchval < values[mid])
▪ Then recursively call binSearch to the LEFT
◼ else if (searchval > values[mid])
▪ Then recursively call binSearch to the RIGHT
◼ If low ever becomes greater than high
◼ This means that searchval is NOT in the array

Kumkum Saxena Recursion page 85


◼ In many cases an algorithm expressed
recursively is more concise than when
expressed iteratively.
◼ In general, recursive algorithms run slower
and require more memory than do iterative
algorithms.
◼ This often leads to a trade-off between efficiency
and simplicity of expression.
◼ There are two types of recursion
◼ Direct recursion is when a function contains a call
to itself within its own body.
◼ The factorial function is an example of direct recursion.

Kumkum Saxena Recursion page 86


◼ Indirect recursion is when a function calls a
second function which in turn calls the first
function.
void g( ) {
f ( ); // indirect recursive call
}
void f ( ) {
g ( );
}
void main ( ) {
f ( );
}
Kumkum Saxena Recursion page 87
Types of Recursion
◼ Linear Recursion-A linear recursive function
is a function that only makes a single call to
itself each time the function runs (as opposed
to one that would call itself multiple times
during its execution). The factorial function is
a good example of linear recursion.

Kumkum Saxena Recursion page 88


◼ Tail Recursion-Tail recursion is a form of
linear recursion.
◼ In tail recursion, the recursive call is the last
thing the function does.
◼ Often, the value of the recursive call is
returned.
◼ As such, tail recursive functions can often be
easily implemented in an iterative manner; by
taking out the recursive call and replacing it
with a loop, the same effect can generally be
achieved.
Kumkum Saxena Recursion page 89
◼ A good example of a tail recursive function is
a function to compute the GCD, or Greatest
Common Denominator, of two numbers:
int gcd(int m, int n)
{
int r;
if (m < n) return gcd(n,m);
r = m%n;
if (r == 0) return(n);
else return(gcd(n,r));
}

Kumkum Saxena Recursion page 90


Binary Recursion
◼ Some recursive functions don't just have one
call to themself, they have two (or more).
Functions with two recursive calls are
referred to as binary recursive functions.

Kumkum Saxena Recursion page 91


Exponential recursion

◼ An exponential recursive function is one that,


if you were to draw out a representation of all
the function calls, would have an exponential
number of calls in relation to the size of the
data set (exponential meaning if there were n
elements, there would be O(an) function calls
where a is a positive number).

Kumkum Saxena Recursion page 92


Nested Recursion

◼ In nested recursion, one of the arguments to


the recursive function is the recursive function
itself.

Kumkum Saxena Recursion page 93

You might also like