2. Recursive Functions
• Recursive functions are functions that
call themselves.
• Data structures, especially linked
implementations of binary
trees, sometimes use recursive functions.
2
3. Example: Factorial Function
• The factorial function is often written as a
recursive function.
• The factorial of a positive integer is the
product of all positive integers less than or
equal to the number.
5 factorial is written 5!
5! = 5 * 4 * 3 * 2 * 1 = 120
3! = 3 * 2 * 1 = 6
0! is defined to be 1
3
4. Factorial Function
1 int factorial( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial( num – 1 );
6 }
The recursive function call
4
5. What Happens When
a Function Calls Itself?
• When a function calls itself, it is not
actually executing itself again.
• Instead, another function is made which is
identical.
• Then, that function is called from the
recursive function call.
• This will be illustrated in the slides that
follow…
5
6. Recursive Process
x = factorial( 4 );
A function call that should produce
24 as a result and assign it to x.
6
7. Recursive Process
(cont.)
x = factorial( 4 );
4 is passed into num
int factorial( int num )
{ 4 4 4 replaces each
if ( num == 0 || num == 1 ) occurrence of num
return 1;
return num * factorial( num – 1 );
} 4 4
7
8. Recursive Process
(cont.)
x = factorial( 4 );
A recursive function call
int factorial( int num ) is made – an identical
{ 4 4 factorial function is made
if ( num == 0 || num == 1 ) and called.
return 1;
return num * factorial( 3 );
} 4
8
9. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
{ 4 4
if ( num == 0 || num == 1 )
return 1;
return num * factorial( 3 );
}
4 3 is passed into num
int factorial( int num )
3 replaces each
{ 3 3 occurrence of num
if ( num == 0 || num == 1 )
return 1;
return num * factorial( num – 1 );
} 3 3
9
10. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
{ 4 4
if ( num == 0 || num == 1 )
return 1;
return num * factorial( 3 );
}
4
int factorial( int num ) A recursive function
{ 3 call is made – an
3
if ( num == 0 || num == 1 ) identical factorial
return 1; function is made
return num * factorial( 2 ); and called.
} 3
10
11. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num ) int factorial( int num )
{ 4 4 { 2
if ( num == 0 || num == 1 )
2
return 1; if ( num == 0 || num == 1 )
return num * factorial( 3 ); return 1;
}
4 return num * factorial( num – 1 );
} 2 2
int factorial( int num )
{ 3 3
if ( num == 0 || num == 1 ) 2 gets passed into num
return 1;
return num * factorial( 2 );
}
3 2 replaces each
occurrence of num
11
12. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num ) int factorial( int num )
{ 4 4 { 2
if ( num == 0 || num == 1 )
2
return 1; if ( num == 0 || num == 1 )
return num * factorial( 3 ); return 1;
} return num * factorial( 1 );
4
} 2
int factorial( int num )
{ 3 3 A recursive function
if ( num == 0 || num == 1 )
return 1;
call is made – an
return num * factorial( 2 ); identical factorial
}
3 function is made and
called.
12
13. Recursive Process
x = factorial( 4 );
(cont.)
1 is
int factorial( int num )
int factorial( int num )
{ 2 2 passed
{ 4 4
if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 ) into num
return 1;
return 1;
return num * factorial( 3 ); return num * factorial( 1 );
}
} 2
4
int factorial( int num ) int factorial( int num )
{ 3 3 { 1 1
if ( num == 0 || num == 1 )
return 1; if ( num == 0 || num == 1 )
return num * factorial( 2 ); return 1;
}
3 return num * factorial( num – 1 );
} 1 1
13
14. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
int factorial( int num )
{ 2 2
{ 4 4 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1;
return 1;
return num * factorial( 3 ); return num * factorial( 1 );
}
} 2
4
int factorial( int num )
int factorial( int num )
{ 1 1
{ 3 3 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1; return 1;
return num * factorial( num – 1 );
return num * factorial( 2 ); }
} 1 1
3
Where is 1 returned?
14
15. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
int factorial( int num )
{ 2 2
{ 4 4 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1;
return 1;
return num * factorial( 3 ); return num * factorial( 1 );
}
} 2
4
int factorial( int num )
int factorial( int num )
{ 1 1
{ 3 3 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1; return 1;
return num * factorial( num – 1 );
return num * factorial( 2 ); }
} 1 1
3
The 1 replaces the function call that
called this function (just as we would
expect with any function call)
15
16. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
int factorial( int num )
{ 2 2
{ 4 4 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1;
return 1;
return num * factorial( 3 ); return num * 1;
}
} 2
4
int factorial( int num )
int factorial( int num )
{ 1 1
{ 3 3 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1; return 1;
return num * factorial( num – 1 );
return num * factorial( 2 );
}
} 1 1
3
The last function has finished
16
17. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
int factorial( int num )
{ 2 2
{ 4 4 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1;
return 1;
return num * factorial( 3 ); return 2;
}
}
4
int factorial( int num ) The execution of this
{ 3 3 return statement can now
if ( num == 0 || num == 1 )
return 1; resume
return num * factorial( 2 );
}
3
17
18. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
int factorial( int num )
{ 2 2
{ 4 4 if ( num == 0 || num == 1 )
if ( num == 0 || num == 1 )
return 1;
return 1;
return num * factorial( 3 ); return 2;
}
}
4
int factorial( int num ) It now returns 2 back
{ 3 3 to the function call
if ( num == 0 || num == 1 )
return 1; that called this
return num * factorial( 2 ); function.
}
3
18
19. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
{ 4 4
if ( num == 0 || num == 1 )
return 1;
return num * factorial( 3 );
}
4
int factorial( int num )
{ 3 3
if ( num == 0 || num == 1 )
return 1;
return 6;
}
19
20. Recursive Process
x = factorial( 4 );
(cont.)
int factorial( int num )
{ 4 4
if ( num == 0 || num == 1 )
return 1;
return num * 6;
}
4
int factorial( int num )
{ 3 3
if ( num == 0 || num == 1 )
return 1;
return 6;
}
20
21. Recursive Process
(cont.)
x = factorial( 4 );
int factorial( int num )
{ 4 4
if ( num == 0 || num == 1 )
return 1;
return 24;
}
21
23. Base Case
Notice that these
1 int factorial( int num )
lines stopped the
2 {
3 if ( num == 0 || num == 1 ) recursion – without
these lines, the
4 return 1;
function will call
5 return num * factorial( num – 1 );
6 } itself over and over
again (infinite
recursion)
23
24. Base Case (cont.)
These lines are
1 int factorial( int num )
called the base
2 {
3 if ( num == 0 || num == 1 ) case – the case
that stops the
4 return 1;
recursion.
5 return num * factorial( num – 1 );
6 }
24
25. Recursive Case
1 int factorial( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial( num – 1 );
6 }
This line that produces a recursive function call
is called the recursive case.
All recursive functions have a base case and a
recursive case (and sometimes more than one
of each).
25
26. What If?
1 int factorial( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial( num – 1 );
6 }
If one makes a mistake and inputs a negative
number into this function:
factorial( -2 );
what will happen?
26
27. Infinite Recursion
1 int factorial( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial( num – 1 );
6 }
If one makes a mistake and inputs a negative
number into this function:
factorial( -2 );
what will happen? Infinite recursion.
27
28. Drivers
1 int factorial2( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial2( num – 1 );
6 }
In order to prevent this problem, we can change
the name of this function to factorial2…
28
29. Drivers (cont.)
1 int factorial2( int num )
2 {
3 if ( num == 0 || num == 1 )
4 return 1;
5 return num * factorial2( num – 1 );
6 }
and then write a factorial function, called a
driver, to call this function…
29
30. Drivers (cont.)
int factorial( int num )
{
if ( num < 0 ) {
cout <<
“The factorial of a negative number is undefined”
<< endl;
return 0;
}
return factorial2( num );
}
30
31. Guidelines
• There must be a base case that stops recursion.
• Each recursive call should approach the base
case.
• The recursive function call should work for the
base case.
• The recursive function call should work for the
case next to the base case.
• The recursive function should make logical
sense, assuming that the recursive function call
inside it does everything it should do.
31
32. Example
• When you know the case next to the base
case works, you know factorial( 2 ) works.
• Since 3! = 3 * factorial( 2 ), you know
factorial( 3 ) works – makes logical sense.
• Since 4! = 4 * factorial( 3 ) and you know
that factorial( 3 ) works, you know that
factorial( 4 ) works.
• Etc., etc.
32
33. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false;
if ( ptr->info == target ) {
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
Searching for a Mercedes in the linked list:
Car mercedes, foundCar;
…
bool found = search( start, foundCar, mercedes ); 33
34. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false; Overloaded
if ( ptr->info == target ) { operator in Car
foundItem = ptr->info; struct
return true;
}
return search( ptr->next, foundItem, target );
}
34
35. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false;
if ( ptr->info == target ) {
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
Returns true if in list; returns false otherwise.
35
36. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL ) If true is returned,
return false; foundItem will be
if ( ptr->info == target ) { assigned Mercedes
foundItem = ptr->info; (passed by reference
return true; on each recursive
} call)
return search( ptr->next, foundItem, target );
}
36
37. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL ) Two
return false; base
if ( ptr->info == target ) { cases
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
37
38. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false;
if ( ptr->info == target ) {
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
Don’t forget the return ( it is a common mistake)…
38
39. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false;
if ( ptr->info == target ) {
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
It passes the true/false value (from base cases) back
through the succession of recursive function calls.
39
40. Recursion on a
Linked List (cont.)
bool search( Node<T> *ptr, T& foundItem, T& target)
{
if ( ptr == NULL )
return false;
if ( ptr->info == target ) {
foundItem = ptr->info;
return true;
}
return search( ptr->next, foundItem, target );
}
Advances pointer in a recursive function call
40
41. Recursion on a
Linked List (cont.)
1 void discount( Node<T> *ptr )
2 {
3 if ( ptr != NULL ) {
4 ptr->info.price -= 0.1 * ( ptr->info.price );
5 discount( ptr->next );
6 }
7 }
Discounts all Car prices in a linked list by 10%
41
42. Recursion on a
Linked List (cont.)
1 void discount( Node<T> *ptr )
2 {
3 if ( ptr != NULL ) {
4 ptr->info.price -= 0.1 * ( ptr->info.price );
5 discount( ptr->next );
6 }
7 }
Recursive call – no return necessary (void return type)
42
43. Recursion on a
Linked List (cont.)
1 void discount( Node<T> *ptr )
2 {
3 if ( ptr != NULL ) {
4 ptr->info.price -= 0.1 * ( ptr->info.price );
5 discount( ptr->next );
6 }
7 }
Where is the base case?
43
44. Recursion on Linked Lists (cont.)
1 void discount( Node<T> *ptr )
2 {
3 if ( ptr != NULL ) {
4 ptr->info.price -= 0.1 * ( ptr->info.price );
5 discount( ptr->next );
6 }
7 }
The base case exists, it just does not need to be written.
When ptr == NULL, it is the base case. The only thing that
needs to be done for the base case is to return.
44
45. Tower of Hanoi
• Three pegs are provided to hold disks. The first
peg has a stack of n disks that are arranged
from bottom to top by decreasing size.
• The goal is to move the stack from the first peg
to the last peg under the following rules:
– Exactly one disk is moved at a time.
– A larger disk should never be placed above a smaller
disk.
45
46. Tower of Hanoi (cont.)
• Example: Initial stack of 3 disks all placed
at Peg A.
1
2
3
Peg A Peg B Peg C
46
47. Tower of Hanoi (cont.)
• Step 1: Move disk 1 from Peg A to Peg C.
2
3 1
Peg A Peg B Peg C
47
48. Tower of Hanoi (cont.)
• Step 2: Move disk 2 from Peg A to Peg B.
3 2 1
Peg A Peg B Peg C
48
49. Tower of Hanoi (cont.)
• Step 3: Move disk 1 from Peg C to Peg B.
1
3 2
Peg A Peg B Peg C
49
50. Tower of Hanoi (cont.)
• Step 4: Move disk 3 from Peg A to Peg C.
1
2 3
Peg A Peg B Peg C
50
51. Tower of Hanoi (cont.)
• Step 5: Move disk 1 from Peg B to Peg A.
1 2 3
Peg A Peg B Peg C
51
52. Tower of Hanoi (cont.)
• Step 6: Move disk 2 from Peg B to Peg C.
2
1 3
Peg A Peg B Peg C
52
53. Tower of Hanoi (cont.)
• Step 7: Move disk 1 from Peg A to Peg C.
1
2
3
Peg A Peg B Peg C
53
54. Tower of Hanoi (cont.)
• Goal achieve: The stack is moved to Peg
C.
1
2
3
Peg A Peg B Peg C
54
55. Tower of Hanoi (cont.)
• If there is 1 disk in the stack, the total number of
moves is 1 (21 - 1).
• If 2 disks … moves is 3 (22 - 1).
• If 3 disks … moves is 7(23 - 1).
• Hence, if there are n disks…, the total number of
moves is 2n – 1.
55
56. Tower of Hanoi (cont.)
1 void TowerOfHanoi (int n,
2 string source, string temp, string destination) {
3 if (n == 1) // base case
4 cout << "Move disk " << n << " from "
5 << source << " to " << destination << endl;
6 else {
7 TowerOfHanoi (n - 1, source, destination, temp);
8 cout << "Move disk " << n << " from "
9 << source << " to " << destination << endl;
10 TowerOfHanoi (n - 1, destination, temp, source);
11 }
12 }
56
57. References
• Childs, J. S. (2008). Recursion. C++
Classes and Data Structures. Prentice
Hall.
57