RECURSION
What is recursion?
a function calls itself
direct recursion indirect recursion
a function calls its invoker
f1
f f2
2
Recursion
is an alternative to iteration (loop)
often more "elegant" and concise than a loop sometimes very inefficient a problem can be defined in terms of successive smaller problems of the same type, i.e. recursively eventually the problem gets small enough that the answer is known (base case) reducing the problem size leads to the base case
recursion should be considered when
sometimes the "work" of the algorithm is done after the base case is reached
3
Outline of a Recursive Function
if (answer is known) provide the answer else make a recursive call to solve a smaller version of the same problem
base case recursive case - leap of faith
4
Factorial (n) - recursive
Factorial (n) = n * Factorial (n-1) for n > 0 Factorial (0) = 1 int RecFact (int n) { if (n > 0) base case return n * RecFact (n-1); else return 1; }
How Recursion Works
a recursive function call is handled like any other function call each recursive call has an activation record on the stack
stores values of parameters and local variables
when base case is reached return is made to previous call
the recursion unwinds
6
Recursive Call Tree
RecFact (4)
int RecFact (int n) { if (n > 0) return n * RecFact (n-1); else return 1; } 4 24 6 2
3
2 1 0
1
1
7
Factorial (n) - iterative
Factorial (n) = n * (n-1) * (n-2) * ... * 1 for n > 0 Factorial (0) = 1 int IterFact (int n) { int fact =1; for (int i = 1; i <= n; i++) fact = fact * i; return fact; }
Another Recursive Definition
Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, . 1 for n == 1 fib(n) = 1 for n == 2 fib(n-2) + fib(n-1) for n>2
Tracing fib(6)
6 5 4 3 2 1
10
4 3 3 1 2 1 2
When to use recursion?
if recursive and iterative algorithms are of similar efficiency --> iteration if the problem is inherently recursive and a recursive algorithm is less complex to write than an iterative algorithm --> recursion recursion often simpler than iteration when it is not tail recursion or there are multiple recursive calls recursion very inefficient when values are recomputed
11
Euclid'sAlgorithm
Finds
the greatest common divisor of two nonnegative integers that are not both 0 Recursive definition of gcd algorithm
gcd (a, b) = a (if b is 0) gcd (a, b) = gcd (b, a % b)
(if b != 0)
Write
a recursive gcd function
prototype? definition?
12
Ackermann's function
A(0, n) = n + 1
A(m+1, 0) = A(m, 1)
A(m+1, n+1) = A(m, A(m+1, n))
13
Iterative gcd
int gcd (int a, int b) { int temp; while (b != 0) { temp = b; b = a % b; a = temp; } return a; }
14
iterative binary search
bool binarySearch (const int a[ ], int numItems, int item) { bool found = false; int first = 0; int last = numItems 1; while (first <= last && ! found) { mid = (first + last) / 2; if (item == a[mid]) found = true; else if (item > a[mid]) first = mid +1; else last = mid 1; } return found; }
15
bool binarySearch(const int a[ ], int first, int last, int item) { if (first > last) return false; // base case 1 (unsuccessful search) else { int mid = (first + last) / 2; if (item == a[mid]) return true; // base case 2 (successful search) else if (item > a[mid]) return binarySearch(a, mid+1, last, item); // X else return binarySearch(a, first, mid-1, item); // Y } }
a = [1 5 9 12 15 21 29 31]
binarySearch(a, 0, 7, 9) true
0, 7, 3
binarySearch(a, 0, 7, 6) false
0, 7, 3
X
0, 2, 1
true
X
0, 2, 1
false
Y true base case 2
2, 2, 2
false
Y
2, 2, 2
X
2, 1,
false
base case 1
17
What Does a Compiler Do?
Lexical
analysis
divide a stream of characters into a stream of tokens
total = cost + 0.08 * cost; if ( ( cond1 && ! cond2 ) )
Parsing
do the tokens form a valid program, i.e. follow the syntax rules?
Generate
object code
18
BNF (Backus-Naur form)
a
language used to define the syntax rules of a programming language consists of
productions rules for forming some construct of the language meta-terms symbols of BNF terminals appear as shown non-terminals syntax defined by another production
19
Syntax Rules
for a simplified boolean expression
bexpr -> bterm || bterm | bterm bterm -> bfactor && bfactor | bfactor bfactor -> !bfactor|(bexpr)|true|false|ident ident -> alpha {alpha|digit|_} alpha -> a .. z | A .. Z digit -> 0 .. 9
meta-terms are in red terminals are in blue non-terminals are in black
20
bexpr -> bterm || bterm | bterm
does
a sequence of tokens form a valid bexpr? if (there is a valid bterm) if (nextToken is ||) if (there is a valid bterm) return true else return false else return true else return false
21
big Oh Notation
Comparing Algorithms and ADT Data Structures
22
Algorithm Efficiency
a measure of the amount of resources consumed in solving a problem of size n
time space
benchmarking code the algorithm, run it with some specific input and measure time taken
better for measuring and comparing the performance of processors than for measuring and comparing the performance of algorithms
Big Oh (asymptotic analysis) provides a formula that associates n, the problem size, with t, the processing time required to solve the problem
23