290 likes | 304 Views
Learn how to use recursion to define objects, solve problems, and write algorithms effectively, with examples and methods for verification.
E N D
Recursion Rosen 5th ed., §3.4-3.5
Recursion • Sometimes, defining an object explicitly might be difficult. • Recursion is a process of defining an object in terms of itself (or of part of itself). • Recursion can be used to define: • Functions • Sequences • Sets • Problems • Algorithms
Recursion vs Induction • Using recursion, we define an object (e.g., a function, a predicate or a set) over an infinite number of elements by defining large size objects in terms of smaller size ones. • In induction, we prove all members of an infinite set have some predicate P by proving the truth for large size objects in terms of smaller size ones.
Recursively Defined Functions • One way to define a function f:NS (for any set S) or series an=f(n) is to: • Define f(0). • For n>0, define f(n) in terms of f(0),…,f(n−1). • E.g.: Define the series an :≡2n recursively: • Let a0 :≡1. • For n>0, let an:≡2an-1.
The Fibonacci Series • The Fibonacci seriesfn≥0 is a famous series defined by:f0 :≡ 0, f1 :≡ 1, fn≥2 :≡ fn−1 + fn−2 0 1 1 2 3 5 8 13 Leonardo Fibonacci1170-1250
Use Recursive Definition to Prove Various Properties • Theorem: fn < 2n. • Proof: By induction. Base cases: f0 = 0 < 20 = 1f1 = 1 < 21 = 2 Inductive step: Use strong induction. Assume k<n, fk < 2k. Then fn = fn−1 + fn−2 is < 2n−1 + 2n−2 < 2n−1 + 2n−1 = 2n. ■ Implicitly for all nN Note use ofbase cases ofrecursive def’n.
Recursively Defined Sets • An infinite set S may be defined recursively, by giving: • A small finite set of base elements of S. • A rule for constructing new elements of S from previously-established elements. • Implicitly, S has no other elements but these. • Example: Let 3S, and let x+yS if x,yS. What is S?
Recursive Problems and Algorithms (§3.5) • Sometimes, the best way to solve a problem is by solving a smaller version of the exact same problem first. • Recursion is a technique that solves a problem by solving a smaller problem of the same type.
1 if n = 0 n!= (recursive solution) (n-1)!*n if n > 0 1 if n = 0 n!= (closed form solution) 1*2*3*…*(n-1)*n if n > 0 Problems defined recursively • There are many problems whose solution can be defined recursively: • Example: n factorial
Coding the factorial function • Recursive implementation int Factorial(int n) { if (n==0) // base case return 1; else return n * Factorial(n-1); }
Another example: n choose k (combinations) • Given n things, how many different sets of size k can be chosen? n n-1 n-1 = + , 1 < k < n (recursive solution) k k k-1 n n! = , 1 < k < n (closed-form solution) k k!(n-k)! with base cases: n n = n (k = 1), = 1 (k = n) 1 n
n choose k (combinations) int Combinations(int n, int k) { if(k == 1) // base case 1 return n; else if (n == k) // base case 2 return 1; else return(Combinations(n-1, k) + Combinations(n-1, k-1)); }
How do I write a recursive function? • Determine the size factor • Determine the base case(s) (the one(s) for which you know the answer) • Determine the general case(s) (the one(s) where the problem is expressed as a smaller version of itself) • Verify the algorithm (use the "Three-Question-Method")
Three-Question Verification Method • The Base-Case Question: Is there a non-recursive way out of the function, and does the routine work correctly for this "base" case? • The Smaller-Caller Question: Does each recursive call to the function involve a smaller case of the original problem, leading inescapably to the base case? • The General-Case Question: Assuming that the recursive call(s) work correctly, does the whole function work correctly?
Compute an recursively • Some algorithms are intuitively iterative, however, they could be written recursively too! procedurepower(a≠0: real, nN) ifn = 0 then return 1elsereturna · power(a, n−1)
Recursive Linear Search • Another example proceduresearch(i, j, x) if=xthen location:= ielse if i=j then location:=0 elsesearch(i+1, j, x) j i ....
Recursive binary search • What is the size factor? The number of elements in (info[first] ... info[last]) • What is the base case(s)? (1) If first > last, return false (2) If item==info[midPoint], return true • What is the general case? if item < info[midPoint] search the first half if item > info[midPoint], search the second half
Recursive binary search bool BinarySearch(A[], item, first, last) { int midPoint; if(first > last) // base case 1 return false; else { midPoint = (first + last)/2; if(item < A[midPoint]) return BinarySearch(A, item, first, midPoint-1); else if (item == A[midPoint]) { // base case 2 item = A[midPoint]; return true; } else return BinarySearch(A, item, midPoint+1, last); } }
MergeSort (cont’d) • The merge takes Θ(n) steps, and merge-sort takes Θ(n log n).
Efficiency of Recursive Algorithms • The time and space complexity of a recursive algorithm depend critically on the number of recursive calls it makes. • What happens when a function gets called? int f(int x) { int y; if(x==0) return 1; else { y = 2 * f(x-1); return y+1; } }
2*f(2) 2*f(1) 2*f(1) =f(0) =f(1) =f(2) =f(3)
Recursion vs. Iteration • Iteration can be used in place of recursion • An iterative algorithm uses a looping construct • A recursive algorithm uses a branching structure • Recursive solutions are often less efficient, in terms of both time and space, than iterative solutions • Recursion can simplify the solution of a problem, often resulting in shorter, more easily understood source code
15 Recursion can be very inefficient is some cases
Deciding whether to use a recursive solution • When the depth of recursive calls is relatively "shallow" • The recursive version does about the same amount of work as the non-recursive version • The recursive version is shorter and simpler than the nonrecursive solution