Recursion Rosen 5 th ed., §
Recursion Sometimes, defining an object explicitly might be difficult.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 is a process of defining an object in terms of itself (or of part of itself). Recursion can be used to define: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.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.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:N S (for any set S) or series a n =f(n) is to:One way to define a function f:N S (for any set S) or series a n =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 a n :≡ 2 n recursively:E.g.: Define the series a n :≡ 2 n recursively: –Let a 0 :≡ 1. –For n>0, let a n :≡ 2a n-1.
The Fibonacci Series The Fibonacci series f n≥0 is a famous series defined by: f 0 :≡ 0, f 1 :≡ 1, f n≥2 :≡ f n−1 + f n−2The Fibonacci series f n≥0 is a famous series defined by: f 0 :≡ 0, f 1 :≡ 1, f n≥2 :≡ f n−1 + f n−2 Leonardo Fibonacci
Use Recursive Definition to Prove Various Properties Theorem: f n < 2 n.Theorem: f n < 2 n. Proof: By induction.Proof: By induction. Base cases:f 0 = 0 < 2 0 = 1 f 1 = 1 < 2 1 = 2 Inductive step: Use strong induction. Assume k<n, f k < 2 k. Then f n = f n−1 + f n−2 is < 2 n−1 + 2 n−2 < 2 n−1 + 2 n−1 = 2 n. ■ Note use of base cases of recursive def’n. Implicitly for all n N
Recursively Defined Sets An infinite set S may be defined recursively, by giving: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 3 S, and let x+y S if x,y S. What is S?Example: Let 3 S, and let x+y S if x,y S. 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.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.Recursion is a technique that solves a problem by solving a smaller problem of the same type.
There are many problems whose solution can be defined recursively:There are many problems whose solution can be defined recursively: Example: n factorial Example: n factorial Problems defined recursively 1if n = 0 n!= (recursive solution) (n-1)!*nif n > 0 1if n = 0 n!= (closed form solution) 1*2*3*…*(n-1)*nif n > 0
Coding the factorial function Recursive implementationRecursive implementation int Factorial(int n) { if (n==0) // base case if (n==0) // base case return 1; return 1; else else return n * Factorial(n-1); return n * Factorial(n-1);}
Another example: n choose k (combinations) Given n things, how many different sets of size k can be chosen?Given n things, how many different sets of size k can be chosen? n n-1 n-1 = +, 1 < k < n(recursive solution) = +, 1 < k < n(recursive solution) k k k-1 n n! =, 1 < k < n(closed-form solution) =, 1 < k < n(closed-form solution) k k!(n-k)! with base cases: n n = n (k = 1), = 1 (k = n) = n (k = 1), = 1 (k = n) 1 n 1 n
int Combinations(int n, int k) { if(k == 1) // base case 1 if(k == 1) // base case 1 return n; return n; else if (n == k) // base case 2 else if (n == k) // base case 2 return 1; return 1; else else return(Combinations(n-1, k) + Combinations(n-1, k-1)); return(Combinations(n-1, k) + Combinations(n-1, k-1));} n choose k (combinations)
How do I write a recursive function? Determine the size factorDetermine the size factor Determine the base case(s)Determine the base case(s) (the one(s) for which you know the answer) Determine the general case(s)Determine the general case(s) (the one(s) where the problem is expressed as a smaller version of itself) Verify the algorithmVerify the algorithm (use the "Three-Question-Method")
Three-Question Verification Method 1.The Base-Case Question: Is there a non-recursive way out of the function, and does the routine work correctly for this "base" case? Is there a non-recursive way out of the function, and does the routine work correctly for this "base" case? 2.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? Does each recursive call to the function involve a smaller case of the original problem, leading inescapably to the base case? 3.The General-Case Question: Assuming that the recursive call(s) work correctly, does the whole function work correctly?
Compute a n recursively Some algorithms are intuitively iterative, however, they could be written recursively too!Some algorithms are intuitively iterative, however, they could be written recursively too! procedure power(a≠0: real, n N) if n = 0 then return 1 else return a · power(a, n−1)
Recursive Linear Search Another exampleAnother example procedure search(i, j, x) if =x then location:= i else if i=j then location:=0 else search(i+1, j, x) else search(i+1, j, x).... i j
What is the size factor?What is the size factor? The number of elements in (info[first]... info[last]) What is the base case(s)?What is the base case(s)? (1) If first > last, return false (1) If first > last, return false (2) If item==info[midPoint], return true (2) If item==info[midPoint], return true What is the general case?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; int midPoint; if(first > last) // base case 1 if(first > last) // base case 1 return false; return false; else { else { midPoint = (first + last)/2; midPoint = (first + last)/2; if(item < A[midPoint]) if(item < A[midPoint]) return BinarySearch(A, item, first, midPoint-1); return BinarySearch(A, item, first, midPoint-1); else if (item == A[midPoint]) { // base case 2 else if (item == A[midPoint]) { // base case 2 item = A[midPoint]; item = A[midPoint]; return true; return true; } else else return BinarySearch(A, item, midPoint+1, last); return BinarySearch(A, item, midPoint+1, last); }} Recursive binary search
Divide and Conquer
MergeSort
MergeSort (cont’d)
The merge takes Θ(n) steps, and merge-sort takes Θ(n log n).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.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?What happens when a function gets called? int f(int x) { int y; int y; if(x==0) if(x==0) return 1; return 1; else { else { y = 2 * f(x-1); y = 2 * f(x-1); return y+1; return y+1; }}
=f(3) =f(2) =f(1) 2*f(2) 2*f(1) =f(0)
Recursion vs. Iteration Iteration can be used in place of recursionIteration 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 solutionsRecursive 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 codeRecursion can simplify the solution of a problem, often resulting in shorter, more easily understood source code
Recursion can be very inefficient is some cases 15
Deciding whether to use a recursive solution When the depth of recursive calls is relatively "shallow"When the depth of recursive calls is relatively "shallow" The recursive version does about the same amount of work as the non-recursive versionThe recursive version does about the same amount of work as the non-recursive version The recursive version is shorter and simpler than the nonrecursive solutionThe recursive version is shorter and simpler than the nonrecursive solution