1 / 42

Module 1-10: Recursion

Learn the fundamental steps of a recursive program, the benefits of recursion, and the difference between iterative and recursive approaches. Discover how recursion simplifies code and its impact on speed and memory usage.

vicknair
Download Presentation

Module 1-10: Recursion

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Module 1-10: Recursion

  2. RECURSION: Every recursive program follows the same basic sequence of steps: 1. Initialize the algorithm. Recursive programs often need a seed value to start with. This is accomplished either by using a parameter passed to the function or by providing a gateway function that is nonrecursive but that sets up the seed values for the recursive calculation. 2. Check to see whether the current value(s) being processed match the base case. If so, process and return the value. 3. Redefine the answer in terms of a smaller or simpler sub-problem or sub-problems. 4. Run the algorithm on the sub-problem. 5. Combine the results in the formulation of the answer. 6. Return the results.

  3. RECURSION: A method is recursive if it can call itself; either directly: void f() { ... f() ... } or indirectly: void f() { ... g() ... } void g() { ... f() ... }

  4. RECURSION: You might wonder about the following: Q: Does using recursion usually make your code faster? A: No, maintenance of the stack actually slows your code down. Q: Does using recursion usually use less memory? A: No, it uses more memory (for the stack). Q: Then why use recursion? A: It sometimes makes your code much simpler!

  5. RECURSION: When a recursive call is made, the method clones itself, making new copies of: the code the local variables (with their initial values), the parameters All placed on the stack. Each copy of the code includes a marker (i.e. return address) indicating the current position. When a recursive call is made, the marker in the old copy of the code is just after the call; the marker in the "cloned" copy is at the beginning of the method. When the method returns, that clone goes away, but the previous ones are still there, and know what to execute next because their current position in the code was saved (indicated by the marker – or return address).

  6. RECURSION: Let’s start with factorial, which can be recursive or not. The factorial is defined as follows: Factorial(1) is 1 [base case] For all integers n > 1: Factorial(n) is (n * Factorial(n-1)) [recursive definition] Factorial can be programmed either using iteration, or recursion: unsigned int factorial(unsigned int n) { unsigned int i, result = 1; for(i = 1; i <= n; i++) result *= i; return result; } unsigned int factorial(unsigned int n) { unsigned int result; if (n <= 1) return 1; result = n; while (--n) result *= n; return result; } I Iterative versions

  7. RECURSION: Factorial defined as follows: Factorial(1) is 1 [base case] For all integers n > 1: Factorial(n) is (n * Factorial(n-1)) [recursive definition] Here is the recursive version: unsigned int factorial(unsigned int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); // recursive case } }

  8. RECURSION: For factorial, the recursive version is: * shorter (maybe), * clearer (maybe), * but slower The following slides provide a step-by-step picture of a "trace" of the recursive version of factorial, for the initial call factorial(5):

  9. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } Note how the value of “n” changes as we progress through the recursion. 1 return 5*factorial(4) This is the statement we will follow. We now make a call to the function again. This creates space for a new instance of the factorial function on the stack. 1 - Indicates the sequence/step number.

  10. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) 2 return 4*factorial(3) We now make a call to the function again. This creates space for a new instance of the factorial function on the stack. 1 - Indicates the sequence/step number.

  11. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) 3 return 3*factorial(2) We now make a call to the function again. This creates space for a new instance of the factorial function on the stack. 1 - Indicates the sequence/step number.

  12. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) Note that “n” is now 1, or the base case. This will stop the recursive calls and begin to pop the results from the stack. return 3*factorial(2) 4 return 2*factorial(1) We now make a call to the function again. This creates space for a new instance of the factorial function on the stack. 1 - Indicates the sequence/step number.

  13. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) We have now reached the base case. This returns a 1 and, since we have a value to start with, we can now pop the results. return 3*factorial(2) return 2*factorial(1) 5 return 1 1 - Indicates the sequence/step number.

  14. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) return 3*factorial(2) return 2*factorial(1) Returns 1 (Base case) 6 return 1 1 - Indicates the sequence/step number.

  15. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) return 3*factorial(2) Returns 2*1 7 return 2*factorial(1) return 1 1 - Indicates the sequence/step number.

  16. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) return 4*factorial(3) Returns 3*2 8 return 3*factorial(2) return 2*factorial(1) return 1 1 - Indicates the sequence/step number.

  17. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } return 5*factorial(4) Returns 4*6 9 return 4*factorial(3) return 3*factorial(2) return 2*factorial(1) return 1 1 - Indicates the sequence/step number.

  18. RECURSION: Call to factorial(5) int factorial(int n) { if (n <= 1) { return 1; // base case } else { return n * factorial(n-1); } } 10 Returns 5*24 return 5*factorial(4) return 4*factorial(3) return 3*factorial(2) return 2*factorial(1) return 1 1 - Indicates the sequence/step number.

  19. RECURSION: Let’s now look at something a little bit more complicated. Fibonacci can be defined as follows: Fib(0) is 0 [base case] Fib(1) is 1 [base case] For all integers n > 1: Fib(n) is (Fib(n-1) + Fib(n-2)) [recursive definition] Fibonacci can be programmed either using iteration, or recursion: unsigned int fib(unsigned int N) { unsigned int k1, k2, k3; k1 = k2 = k3 = 1; for (int j = 3; j <= N; j++) { k3 = k1 + k2; k1 = k2; k2 = k3; } return k3; } Iterative version I

  20. RECURSION: Fibonacci defined as follows: Fib(0) is 0 [base case] Fib(1) is 1 [base case] For all integers n > 1: Fib(n) is (Fib(n-1) + Fib(n-2)) [recursive definition] Here is the recursive version : unsigned int fib(unsigned int n) { if (n <= 1) { return n; } else { return fib(n-1)+fib(n-2); } }

  21. RECURSION: For Fibonacci, the recursive version is: * shorter, * clearer, * but slower The following slides provide a step-by-step picture of a "trace" of the recursive version of Fibonacci, for the initial call fib(5):

  22. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) 1 Note how the value of “n” changes as we progress through the recursion. return fib(4)+fib(3) This is the statement we will follow. We now make a call to the function again (specifically fib(4)). This creates space for a new instance of the fib function on the stack. 1 - Indicates the sequence/step number.

  23. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) 2 return fib(3)+fib(2) We now make a call to the function again (specifically fib(3)). This creates space for a new instance of the fib function on the stack. 1 - Indicates the sequence/step number.

  24. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) 3 return fib(2)+fib(1) We now make a call to the function again (specifically fib(2)). This creates space for a new instance of the fib function on the stack. 1 - Indicates the sequence/step number.

  25. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) Note that “n” is now 1, or the base case. This will stop the recursive calls and begin to pop the results from the stack. return fib(3)+fib(2) return fib(2)+fib(1) 4 return fib(1)+fib(0) We now make a call to the function again (specifically fib(1)). 1 - Indicates the sequence/step number.

  26. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) We have now reached the base case. This returns a 1 and, since we have a value to start with, we can now pop the results. return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) return fib(1)+fib(0) 5 return 1 1 - Indicates the sequence/step number.

  27. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) Note we have now satisfied the leftmost fib function call (fib(1)), so we can now make the rightmost function call (fib(0)). This is the pattern we will follow for the remaining steps. return fib(1)+fib(0) Return 1 (Base case) 6 return 1 1 - Indicates the sequence/step number.

  28. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) return fib(1)+fib(0) We now make a call to the rightmost function (fib(0)). 7 return 0 return 1 1 - Indicates the sequence/step number.

  29. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) return fib(1)+fib(0) 8 Return 0 (Base case) return 0 return 1 1 - Indicates the sequence/step number.

  30. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) Return 1+0 We have now satisfied the leftmost and rightmost function calls, so we can return a value. 9 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  31. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) We now make a call to the rightmost function (fib(1)). 10 return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  32. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) return fib(2)+fib(1) 11 Return 1 (Base case) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  33. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) We have now satisfied the leftmost and rightmost function calls, so we can return a value. Return 1+1 12 return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  34. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) We now make a call to the rightmost function (fib(2)). return fib(3)+fib(2) 13 return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  35. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) 13 return fib(1)+fib(0) return fib(2)+fib(1) 14 - 17 return 1 Note that we have the same situation now as we did before. So the results will be the same. These would be steps 14 -17. return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  36. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(3)+fib(2) Return 1+0 18 return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) We have now satisfied the leftmost and rightmost function calls, so we can return a value. return 0 return 1 1 - Indicates the sequence/step number.

  37. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) We have now satisfied the leftmost and rightmost function calls, so we can return a value. Return 2+1 19 return fib(3)+fib(2) return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  38. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) We now make a call to the rightmost function (fib(3)). return fib(4)+fib(3) 20 return fib(2)+fib(1) return fib(3)+fib(2) return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  39. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) return fib(2)+fib(1) return fib(3)+fib(2) 21 - 28 return fib(1)+fib(0) return fib(2)+fib(1) Note that we have the same situation now as we did before. So the results will be the same. These would be steps 21 -28. return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  40. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) return fib(4)+fib(3) Return 1+1 29 return fib(2)+fib(1) return fib(3)+fib(2) We have now satisfied the leftmost and rightmost function calls, so we can return a value. return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

  41. RECURSION: int fib(int n) { if (n <= 1) return n; else return fib(n-1)+fib(n-2); } Call to fib(5) Return 3+2 30 return fib(4)+fib(3) return fib(2)+fib(1) return fib(3)+fib(2) We have now satisfied the leftmost and rightmost function calls, so we can return a value. return fib(1)+fib(0) return fib(2)+fib(1) return 1 return fib(1)+fib(0) return 0 return 1 1 - Indicates the sequence/step number.

More Related