Data Structures
Recursion Review
14-Recursion 1
Recursive Function (1)
• A function is one that calls itself is called recursive function
void Message(void)
{
cout << "This is a recursive function.\n";
Message();
}
• What is the problem with the above function?
– No code to stop it from repeating (i.e., calling itself)
– Function behaves like an infinite loop
14-Recursion 2
Recursive Function – Number of Repetitions
• Recursive function must have some algorithm (i.e., logic) to control
the number of times it repeats
void Message(int times)
{
if (times > 0)
{
cout << "This is a recursive function.\n";
Message(times - 1);
}
return;
}
• Modification to Message function
– Receive an int argument to control the number to times to call itself
14-Recursion 3
Recursive Function – Execution (1)
• Each time the function is called, a new instance of the times
parameter is created
– Suppose program invokes the function as Message(5)
1st call of the function In the first call to function,
times is set to 5.
Value of times: 5
2nd call of the function When the function calls
itself, a new instance of
Value of times: 4 times is created with the
value 4.
14-Recursion 4
Recursive Function – Execution (2)
void Message(int times)
1st call of the function {
if (times > 0)
Value of times: 5 {
cout << "This is a recursive function.\n";
Message(times - 1);
2nd call of the function }
return;
Value of times: 4 }
3rd call of the function
Value of times: 3
4th call of the function
Value of times: 2
5th call of the function
Value of times: 1
• This cycle repeats itself until 0 is
passed to the function 6th call of the function
• Depth of recursion: 6
Value of times: 0
14-Recursion 5
Recursive Function – Modification
• Statements after the recursive invocation of the function
void Message(int times)
{
cout << "Message called with " << times <<" in times.\n";
if (times > 0) {
cout << "This is a recursive function.\n";
Message(times - 1);
}
cout << "Message returning with " << times;
cout << " in times.\n";
}
14-Recursion 6
Recursive Function – Execution (3)
1st call of the function Message called with 5 in times.
This is a recursive function.
Value of times: 5 Message returning with 5 in times.
Message called with 4 in times.
2nd call of the function
This is a recursive function.
Value of times: 4 Message returning with 4 in times.
Message called with 3 in times.
3rd call of the function
This is a recursive function.
Value of times: 3 Message returning with 3 in times.
Message called with 2 in times.
4th call of the function
This is a recursive function.
Value of times: 2 Message returning with 2 in times.
Message called with 1 in times.
5th call of the function
This is a recursive function.
Value of times: 1 Message returning with 1 in times.
6th call of the function
Message called with 0 in times.
Message returning with 0 in times. Value of times: 0
7
Recursion (1)
• Solving a problem by reducing it to a smaller version of itself
• A properly written recursive function must
– Handle the base case, and
– Convergence to the base case
• Failure to properly handle the base case or converge to the base
case (divergence) may result in infinite recursion
14-Recursion 8
Recursion (2)
• To solve problem recursively
1. Define the base case(s)
2. Define the recursive case(s)
a) Divide the problem into smaller sub-problems
b) Solve the sub-problems
c) Combine results to get answer
Sub-problems solved as a recursive call to the same function
• Sub-problem must be smaller than the original problem
– Otherwise, recursion never terminates
14-Recursion 9
Example: Binary Search
int binarySearch(int array[], int value, int first, int last) {
if (first > last ) return -1; // Base case
int mid = (first + last)/2;
if (array[mid] == value) {
return mid;
}
else if (array [mid] < value){
return binarySearch(array, value, mid+1, last);
}
else { // last possibility: arrray[mid] > value
return binarySearch(array, value, first, mid-1);
}
}
14-Recursion 10
Example: Factorial Function (1)
public static int fac(int n) {
if (n <= 1) {
return 1;
}
else {
return n * fac(n - 1);
}
}
14-Recursion 11
Example: Factorial Function (1)
• Suppose the factorial function is invoked as fac(5)
fac(5)
5 * fac(4)
5 * 4 * fac(3)
5 * 4 * 3 * fac(2)
5 * 4 * 3 * 2 * fac(1)
5 * 4 * 3 * 2 * 1
5 * 4 * 3 * 2
5 * 4 * 6
5 * 24
120
14-Recursion 12
Stack Overflow (1)
• Recursive functions cannot use statically allocated local variables
– Each instance of the function needs its own copies of local variables
• Most modern languages allocate local variables for functions on the
run-time stack
• Calling a recursive function many times or with large arguments
may result in stack overflow
$ java Fac 10000
Exception in thread "main" java.lang.StackOverflowError
at Fac.facIter(Fac.java:35)
at Fac.facIter(Fac.java:38)
at Fac.facIter(Fac.java:38)
...
14-Recursion 13
Stack Overflow (2)
• Three ways to deal with stack overflow:
– Limit input size (Brittle: How to know limit on a particular machine?)
– Increase stack size (brittle – how to know how big?)
– Replace recursion with iteration
public static int facIterative(int n) {
int factorialAccumulator = 1;
for (int x = n; x > 0; x--) {
factorialAccumulator *= x;
}
return factorialAccumulator;
}
• Recursive definitions are often more natural
– Imperative/iterative definitions often perform better
14-Recursion 14
Example: Linked List Operations
• Many operations on linked lists may be implemented by using
recursion
• We will discuss two functions:
– Counting the number of nodes in a list
– Displaying the value of the list nodes in reverse order
14-Recursion 15
Counting Nodes in The List
• The function's recursive logic can be expressed as
int List::countNodes(Node *nodePtr)
{
if (nodePtr != NULL)
return 1 + countNodes(nodePtr->next);
else
return 0;
}
• What is the base case?
– nodePtr being equal to NULL
14-Recursion 16
Displaying List Nodes in Reverse Order
• The function's recursive logic can be expressed as
void List::showReverse(Node *nodePtr)
{
if (nodePtr != NULL)
{
showReverse(nodePtr->next);
cout << nodePtr->value << " ";
}
}
• The base case for the function is nodePtr being equal to NULL
14-Recursion 17
Recursion or Iteration?
CLARITY EFFICIENCY
14-Recursion 18
• Search for an Element in a Linked List:
• Implement a recursive function to search for a specific element in a linked list.
•
• Delete a Node in a Linked List:
• Write a recursive function to delete a node with a specific value from a linked list.
19
• Find the Middle of a Linked List:
• Find the middle element of a linked list using a recursive approach. You can use two
pointers, one slow and one fast, to find the middle node.
•
• Reverse a Linked List:
• Implement a recursive function to reverse a singly linked list. The idea is to reverse
the next pointers of each node to point to the previous node recursively.
20