1 / 25

Lecture 12: Eliminating Recursion

CSC 313 – Advanced Programming Topics. Lecture 12: Eliminating Recursion. Why Recurse ?. Recursion is useful, powerful technique Often yields compact, easy-to-read code Highlights all possible cases making testing simple Some algorithms naturally recursive

yuki
Download Presentation

Lecture 12: Eliminating 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. CSC 313 – Advanced Programming Topics Lecture 12:Eliminating Recursion

  2. Why Recurse? • Recursion is useful, powerful technique • Often yields compact, easy-to-read code • Highlights all possible cases making testing simple • Some algorithms naturally recursive • Divide-and-conquer algorithms • Nearly anything that uses a tree • LISP & other functional language programs • Recursion can reduce development time

  3. Why Not Use Recursion? • Often means values computed repeatedly • Cannot store interim results between calls • Short, simple methods limit optimizations • Behavior varies widely between calls • Compiler cannot optimize over method calls • Requires lots of method calls • But good design emphasizes calling methods • Cannot say this is bad in other cases • Why are recursive method calls bad?

  4. Why Not Use Recursion? • Often means values computed repeatedly • Cannot store interim results between calls • Short, simple methods limit optimizations • Behavior varies widely between calls • Compiler cannot optimize over method calls • Requires lotsLOTSof method calls • But good design emphasizes calling methods • Cannot say this is bad in other cases • Why are recursive method calls bad?

  5. Why Not Use Recursion? • Often means values computed repeatedly • Cannot store interim results between calls • Short, simple methods limit optimizations • Behavior varies widely between calls • Compiler cannot optimize over method calls • Requires lotsLOTSTONSof method calls • But good design emphasizes calling methods • Cannot say this is bad in other cases • Why are recursive method calls bad?

  6. Method Call Overhead • Every method call has some overhead • Load address of method to be called • Allocate stack memory for method • Push parameters onto a stack • Push return value from stack • Reload return address from the stack • Deallocate stack memory

  7. Pain of Recursion • Compiler optimizes much of method call • Most become only 1 instruction • Leaves allocating stack space as main cost • Program starts by allocating huge stack • Then optimizes assuming stack is immobile • But lots of concurrent method calls will fill this • Rarely code many nested calls…

  8. Pain of Recursion • Compiler optimizes much of method call • Most become only 1 instruction • Leaves allocating stack space as main cost • Program starts by allocating huge stack • Then optimizes assuming stack is immobile • But lots of concurrent method calls will fill this • Rarely code many nested calls…except when using recursion

  9. QuickSort Results • Code same QuickSort algorithm 2 ways: • Recursively • Iteratively • Computed average of 10 trials for 3 data sizes • Increasing size also increases chance of crashing

  10. What Can We Do? • Convert algorithm to use tail-recursion • Make recursive call as last step of recursion • Should directly return result of recursive call public int factorial(inti) { if (i <= 1) { return 1; } else {int result = factorial(i – 1); return result * i; }}

  11. What Can We Do? • Convert algorithm to use tail-recursion • Make recursive call as last step of recursion • Should directly return result of recursive call public int factorial(inti) { if (i <= 1) { return 1; } else { return i * factorial(i – 1); }}

  12. What Can We Do? • Convert algorithm to use tail-recursion • Make recursive call as last step of recursion • Should directly return result of recursive call public int factorial(inti, int fact) { if (i <= 1) { return fact; } else { return factorial(i – 1, fact * i); }}

  13. Tail Recursion • Conversion of tail-recursion to iteration easy • Create local variable to track most recent result • Recreate recursionusing for or while loop • Get benefits of simplicity without the costs public int factorial(inti, int fact) { if (i <= 1) { return fact; } else { return factorial(i – 1, fact * i); }}

  14. Tail Recursion • Conversion of tail-recursion to iteration easy • Create local variable to track most recent result • Recreate recursionusing for or while loop • Get benefits of simplicity without the costs public int factorial(inti) {int fact; if (i <= 1) { // Stop recursion } else {fact *= i; // Continue recursion }}

  15. Tail Recursion • Conversion of tail-recursion to iteration easy • Create local variable to track most recent result • Recreate recursionusing for or while loop • Get benefits of simplicity without the costs public int factorial(inti) {int fact = 1; while (i > 1) { fact *= i;i--; } return fact;}

  16. Recursion Elimination • Must first have code that meets criteria • Only for tail recursion (recursion at end) • Works when methodreturns recursive result • Often can rewrite code to meet these needs • Once done, simple to remove recursion • Add local variable storing result as we go • Uses foror whileloop to replace recursion • Easier to optimize code & saves call overhead

  17. Recursion Elimination • Must first have code that meets criteria • Only for tail recursion (recursion at end) • Works when methodreturns recursive result • Often can rewrite code to meet these needs • Once done, simple to remove recursion • Add local variable storing result as we go • Uses foror whileloop to replace recursion • Easier to optimize code & saves call overhead

  18. Tail Recursion Elimination • not all algorithms can be converted • For some algorithms, recursion may be required

  19. Remove Recursion By Cheating • Slow performance due to stack overhead • While cannot always remove recursion • Can remove overhead’s source • Instantiate Stack at beginning of method • Program Stackreplaced with local Stack • Method iterateswhile Stack is not empty • Start loop by popping value to be processed

  20. Remove Recursion By Cheating public void printInOrder(BNode<T> root) {if (root.hasLeft()) {printInOrder(root.leftChild());}System.out.println(root.element());if (root.hasRight()) {printInOrder(root.rightChild());} }

  21. Remove Recursion By Cheating • public void printInOrder(BNode<T> root) {Stack stack = // Instantiate stackstack.push(root);while (!stack.isEmpty()) { Object node = stack.pop();if (node.hasRight()) { push(node.rightChild()); }push(node.element());if (node.hasLeft()) { push(node.leftChild()); }} }

  22. Remove Recursion By Cheating • public void printInOrder(BNode<T> root) {Stack stack = // Instantiate stackstack.push(root);while (!stack.isEmpty()) { Object node = stack.pop();if (node instanceofBNode) {if (node.hasRight()) { push(node.rightChild()); }push(node.element());if (node.hasLeft()) { push(node.leftChild()); }} else { System.out.println(node); }} }

  23. Cheater Removing Recursion • Use local Stack to replace program Stack • Stack handles multiple data types • Pop value off Stack with each iteration • Loop’s actions depend on value’s type • Compiler can now optimize this method • Stackmethods highly optimized • Growing & shrinking this Stack much easier • Single call means better chance of optimizing

  24. Recursion Elimination • To do this, algorithm must be tail recursive • Rewrite code, if possible, before starting • Conversion of tail-recursion to iteration easy • Create local variable to store current result • Use for or while loop to recreate recursion • Use recursive stepas body of the loop • Upon reaching base case should terminate loop • After loop code from base case is performed

  25. For Next Lecture • Lab #3 due before lab time Friday • Asks you to implement Observer Pattern • Read pages 109 – 122 of the book • Within a program, how do you instantiate objects? • Any design principles not violated by new? • Haven’t we already used Pizza in a pattern?

More Related