Recursion as a Problem-Solving Technique
Defining Languages
Language
A set of strings of symbols
C++Programs = {strings s: s is a syntactically correct C++ program}
Grammar
States the rules of the language - the syntax
For C++Programs, the syntax is not within the scope of this discussion.
If the rules are recursive in nature, you can determine if a string is in the
language by using a recognition algorithm.
A recognition algorithm is a process for determining if a string is syntactically
correct based on the rules of the language.
A Simple Language: Palindromes
Language
Palindromes = {string s: s reads the same forwards as backwards}
Grammar
Characters in the string have to be considered in pairs
Rules:
s is a palindrome if and only if:
1. The first and last characters of s are the same
2. s minus its first and last characters is a palindrome
Recognition Algorithm
The set of rules above define a circular argument: you must take the result of Rule #2
and apply the rules again.
This is the essence of recursion - re-application of the rules.
However, you need a base case so that you know when to stop.
Recursive Solution:
1. Define the problem in terms of a smaller problem of the same type
See Rule #2
2. Identify how the recursive call diminishes the size of the problem
The string is shorter by two characters
3. Identify the base case, the point at which the problem no longer diminishes
One way to exit the recursive process comes indirectly from Rule #1:
if ( Rule #1 is false ) s is not a palindrome
If Rule #1 continues to be true, we need a base case.
We actually have two base cases:
1. If s has an even number of characters,
and Rule #1 continues to be true,
we will eventually be left with an empty string.
An empty string is a palindrome.
2. If s has an odd number of characters
and Rule #1 continues to be true,
we will eventually be left with 1 character.
1 character is a palindrome
4. Make certain that the base case can be reached
Yes.
The pseudocode for the recognition algorithm is:
Base Cases : if ( s is an empty string or is of length 1 ) return true
Recursive Call : else if ( Rule #1 is true ) return the result of Rule #2
The Test Failed: else return false
What arguments do we need to pass to our recursive function?
First Call: s
Next Calls : s.substring(1, s.length())
A Simple Language: Algebraic Expressions
Infix - expressions are evaluated based on the precedence of the operator
Parentheses
Exponents
Multiplication
Division
Addition
Subtraction
a + b * c
Prefix - the operator is applied to the two operands that follow it
+ a * b c
One method to convert:
1. Fully parenthesize the infix expression
2. Move the operator to the position marked by its open parenthisis
3. Remove the parentheses
Postfix - the operator is applied to the two operands that precede it
a b c * +
One method to convert:
1. Fully parenthesize the infix expression
2. Move the operator to the position marked by its closed parenthisis
3. Remove the parentheses
Recursive Solution:
We'll leave this as an exercise for a later class.
Towers of Hanoi
(Applet)
Pseudocode
void moveTower(disk, source, dest, spare) {
if (disk == 0 )
move disk from source to dest
else {
moveTower(disk - 1, source, spare, dest)
move disk from source to dest
moveTower(disk - 1, spare, dest, source)
}
}