0% found this document useful (0 votes)
23 views34 pages

09 - Recursion

Uploaded by

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

09 - Recursion

Uploaded by

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

Recursion

CS 302 – Data Structures


Chapter 7
What is recursion?
• A technique that solves problem by solving
smaller versions of the same problem!

• When you turn this into a program, you end


up with functions that call themselves (i.e.,
recursive functions)
Why use recursion?
• Recursive algorithms can simplify the
solution of a problem, often resulting in
shorter, more easily understood source
code.
• But …they are often less efficient, both in
terms of time and space, than non-recursive
(e.g., iterative) solutions.
Recursion vs. Iteration
• Iteration
– Uses repetition structures (for, while or do…
while)
– Repetition through explicitly use of repetition
structure.
– Terminates when loop-continuation condition
fails.
– Controls repetition by using a counter.
Recursion vs. Iteration
• Recursion
– Uses selection structures (if, if…else or
switch)
– Repetition through repeated function calls.
– Terminates when base case is satisfied.
– Controls repetition by dividing problem into
simpler one(s).
General Form of Recursive Functions
Solve(Problem)
{
if (Problem is minimal/not decomposable: a base case)
solve Problem directly; i.e., without recursion
else {
(1) Decompose Problem into one or more similar,
strictly smaller subproblems: SP1, SP2, ... , SPN
(2) Recursively call Solve (this method) on each
subproblem: Solve(SP1), Solve(SP2),..., Solve(SPN)
(3) Combine the solutions to these subproblems into a
solution that solves the original Problem
}
}
n! (n factorial)
• There are many problems whose solution
can be defined recursively

1 if n = 0
n!= (recursive solution)
(n-1)!*n if n > 0

1 if n = 0
n!= (closed form solution)
1*2*3*…*(n-1)*n if n > 0
Coding the factorial function
• Recursive implementation
int Factorial (int n)
{
if (n==0) // base case
return 1;
else
return n * Factorial(n-1); // decompose, solve, combine
}
n choose k (combinations)
• Given n objects, how many different sets of
size k can be chosen?

n n-1 n-1
= + , 1 < k < n (recursive solution)
k k k-1
n n!
= , 1 < k < n (closed-form solution)
k k!(n-k)!
with base cases:
n n
= n (k = 1), = 1 (k = n)
1 n
Coding n choose k (combinations)
int Combinations(int n, int k)
{
if(k == 1) // base case 1
return n;
else if (n == k) // base case 2
return 1;
else
return(Combinations(n-1, k) + Combinations(n-1, k-1));
}
How does the computer
implement recursion?
• It uses a stack called “run-time” stack to
keep track of the function calls.
• Each time a function is called recursively,
an “activation record” is created and stored
in the stack.
• When recursion returns, the corresponding
activation is popped out of the stack.
What happens during
a function call?
int a(int w)
{
return w+1;
}

int b(int x)
{
int z,y;
……………… // other statements
z = a(x) + y;
a() is called here!
return z;
}
What happens during
a function call? (cont.)
• An activation record is stored into the
run-time stack:
1) The system stops executing function b and starts
executing function a
2) Since it needs to come back to function b later, it
needs to store everything about function b that is
going to need (x, y, z, and the place to start executing
upon return)
3) Then, x from a is bounded to w from b
4) Control is transferred to function a
What happens during
a function call? (cont.)
• After function a is executed, the activation
record is popped out of the run-time stack
– All the old values of the parameters and variables in
function b are restored and the return value of function
a replaces a(x) in the assignment statement
Recursive Function Calls
• There is no difference between recursive and non-
recursive calls!

int f(int x)
{
int y;
if(x==0)
return 1;
else {
y = 2 * f(x-1);
return y+1;
}
}
f(3) 2*f(2)

2*f(1)

2*f(1)

=f(0)

=f(1)

=f(2)

=f(3)
Conclusion

• Recursion could be very slow because ofthe extra


memory and time overhead due to function calls!
How do I write a
recursive function?
• Determine the size factor
• Determine the base case(s)
(i.e., the one(s) for which you know the answer)
• Determine the general case(s)
(i.e., the one(s) where the problem is expressed
as a smaller version of itself)
• Verify the algorithm
Three-Question Verification Method
1. The Base-Case Question:
Is there a non-recursive way out of the function,
and does the routine work correctly for this "base"
case?
2. The Smaller-Caller Question:
Does each recursive call to the function involve a
smaller case of the original problem, leading
inescapably to the base case?
3. The General-Case Question:
Assuming that the recursive call(s) work correctly,
does the whole function work correctly?
Binary Search Using Iteration
template<class ItemType>
void SortedType<ItemType>::RetrieveItem(ItemType& item, bool& found)
{
int midPoint;
int first = 0;
int last = length - 1;

found = false;
while( (first <= last) && !found) {
midPoint = (first + last) / 2;
if (item < info[midPoint])
last = midPoint - 1;
else if(item > info[midPoint])
first = midPoint + 1;
else {
found = true;
item = info[midPoint];
}
}
}
Binary Search Using Recursion
• What is the size factor?
The number of elements in (info[first] ... info[last])

• What is the base case(s)?


(1) If first > last, return false
(2) If item==info[midPoint], return true

• What is the general case?


if item < info[midPoint] search the first half
if item > info[midPoint], search the second half
Binary Search Using Recursion
(cont’d)

template<class ItemType>
void SortedType<ItemType>::RetrieveItem
(ItemType& item,
bool& found)
{
found = BinarySearch(info, item, 0, length-1);
}
Binary Search Using Recursion
template<class ItemType>
(cont’d)
bool BinarySearch(ItemType info[], ItemType& item, int first, int last)
{
int midPoint;
if(first > last) // base case 1
return false;
else {
midPoint = (first + last)/2;
if(item < info[midPoint])
return BinarySearch(info, item, first, midPoint-1); // general case 1
else if (item == info[midPoint]) { // base case 2
item = info[midPoint];
return true;
}
else
return BinarySearch(info, item, midPoint+1, last); // general case 2
}
}
Recursive InsertItem (sorted list)

location

location

location

location
Recursive InsertItem (sorted list)
• What is the size factor?
The number of elements in the current list
What is the base case(s)?
1) If the list is empty, insert item into the empty list
2) If item < location->info, insert item at the front in
the current list
• What is the general case?
Insert(location->next, item)
Recursive InsertItem (sorted list)
template <class ItemType>
void SortedType<ItemType>::InsertItem(ItemType newItem)
{
Insert(listData, newItem);
}

template <class ItemType>


void Insert(NodeType<ItemType>* &location, ItemType item)
{
if(location == NULL) || (item < location->info)) { // base cases

NodeType<ItemType>* tempPtr = location;


location = new NodeType<ItemType>;
location->info = item;
location->next = tempPtr;
}
else
Insert(location->next, newItem); // general case
}
Note: no "predLoc" pointer is needed for insertion!
location

= location;
location

location
Recursive DeleteItem (sorted list)

• What is the size factor?


The number of elements in the list
• What is the base case(s)?
If item == location->info, delete node
pointed by location
• What is the general case?
Delete(location->next, item)
Recursive DeleteItem (sorted list)
template <class ItemType>
void SortedType<ItemType>::DeleteItem(ItemType item)
(cont.)
{
Delete(listData, item);
}

template <class ItemType>


void Delete(NodeType<ItemType>* &location, ItemType item)
{
if(item == location->info)) {

NodeType<ItemType>* tempPtr = location;


location = location->next;
delete tempPtr;
}
else
Delete(location->next, item);
}
Recursive DeleteItem (sorted list)

location

location

location
Deciding whether to use a
recursive solution ...
• The recursive version is shorter and simpler than
the non-recursive solution.

• The depth of recursive calls is relatively "shallow“.

• The recursive version does about the same amount


of work as the non-recursive version.
Recursion could be
very inefficient!
C om b (6 ,4 )

= C om b (5 , 3 ) C om b (5 , 4 )
+

= C om b (4 ,2 ) C om b (4 , 3 ) + C om b (4 , 3 ) + C om b (4 , 4 )
+

= C om b (3 , 1 +) + C om b (3 , 2 ) + C om b (3 , 2 ) + C om+ b (3 , 3 ) + C om+ b (3 , 2 ) + C om+ b (3 , 3 ) + 1

= 3 + , 1 ) + C om b (2 , 2 ) + +C om b (2 , 1 ) + C om b (2
+ C om b (2 + , 2) + 1 + +C om b (2 , 1 ) + C om b (2
+ , 2) + 1 + 1+

= 3 + 2 + 1 + 2 + 1 + 1 + 2 + 1 + 1 + 1

= 15

Dynamic programming can avoid this issue!


(see CS477/677)

You might also like