when a function invokes itself A function that invokes itself is said to be nothing new
A common problem solving technique: - break problem down into smaller/simpler sub-problems - solve sub-problems - combine sub-solutions into solution
Write a function that calculates and returns the Factorial of a given integer. factorial(n), written = 1 * 2 * 3 *...* n when n = 0 return 1 when n < 0 return 0 (meaning undefined )
// strictly structured, int f; // non-recursive if (n < 0) // sub-solution 1 f = 0; else if (n == 0) // sub-solution 2 f = 1; else { // sub-solution 3 f = 1; for (int i=1; i<=n; i++) f = f * i; return f;
// simplified non-recursive solution int fact(int n) { int f = 1; //undefined for (int i=1; i<=n; i++) f = f * i; return f;
- - solve the simplest version(s) of the problem, including for bad input - solve a simple piece of the problem - use recursion to solve the rest of the slightly-simplified problem - combine these two sub-solutions into a solution
n! = 1 when n = 0 n * when n > 0 undefined when n < 0 Note: mathematicians like recursive definitions!!
// strictly structured, recursive solution int fact(int n) { int f; if (n < 0) // base case: bad input f = 0; else if (n == 0) // base case: super easy f = 1; else // recursive case: f = n * fact(n-1); // fairly easy plus return f; // simplified recursive
// simplified C++ recursive solution int fact(int n) { return (n * fact(n-1));
return (n * fact(n-1));
return (n * fact(n-1)); cout << ;
{ return (n * fact(n-1)); cout << ;
return 0; return (n * fact(n-1));
return 1; return (n * fact(n-1));
return (n * );
{ return (n * fact(n-1));
return 0; return (n * fact(n-1));
return 1; return (n * fact(n-1));
return (n * );
{ return (n * fact(n-1));
return 0; return (n * fact(n-1));
return 1; return (n * fact(n-1));
return (n * );
{ return (n * fact(n-1));
return 0; return (n * fact(n-1));
return 1; return (n * fact(n-1));
if (n == 0) return (n * fact(n-1));
return (n * );
return
return (n * );
return
return (n * );
return
return (n * fact(n-1)); cout << ;
return (n * fact(n-1));
return (n * fact(n-1));
- simplified (clearer) coding solutions - some programmers (mathematical thinkers) prefer it. - very inefficient (memory & invocation overhead) - danger of Stack Overflow(not enough memory)
Write a recursive function that calculates and returns the power of 2 of a given exponent. It should handle negative exponents and an exponent of 0. ex: 2 3 =8 2-2 = 1/2 2 = ¼ = 0.25 2 0 = 1
- name: pow2() - given (argument): integer exponent - returns a float (to handle negative exponents) - D&C: how to handle negative exponents? return 1 / pow2(-exp) - Base Case: pow2(0) = 1 - Recursive Case: pow2(n) = 2 * pow2(n-1)
float pow2(int e) { float p; if (e < 0) p = 1.0 / pow2(-e); else if (e == 0) p = 1.0; else p = 2 * pow2(e-1); return p;
float pow2(int e) { if (e < 0) return 1.0/pow2(-e); if (e == 0) return 1.0; return (2 * pow2(e-1));
Write a recursive function that counts and returns the number of spaces in a given string. ex: "Go Cats!" 1 "The Univ of Kentucky " 4 "" 0
- name: numspaces() - given (argument): a string - returns an int - Base Case: empty string has 0 spaces - Recursive Case: - count spaces in substring of all but first char - add 1 if first char is space, 0 otherwise
int numspaces(string s) { int ns=0; if (s.empty()) return 0; ns = numspaces(s.substr(1,-1)); if (s[0] == ' ') ns++; return ns; //.substr(): the -1 means to the end
Term Definition when a function invokes itself when the computer is out of memory to allocate variables and arguments.