Download presentation
Presentation is loading. Please wait.
Published byBeatrice Walsh Modified over 9 years ago
1
CSC 313 – Advanced Programming Topics
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 lots LOTS of 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 lots LOTS TONS of 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 Q UICK S ORT algorithm 2 ways: 1. Recursively 2. Iteratively Computed average of 10 trials for 3 data sizes Increasing size also increases chance of crashing Algorithm n = 100 n = 1000 n = 10000 Iterative 1.0 Recursive 1.41.31.1
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(int i) { if (i <= 1) { return 1; } else { int result = factorial(i – 1); return result * i; } }
11
public int factorial(int i) { if (i <= 1) { return 1; } else { return i * factorial(i – 1); } } 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
12
public int factorial(int i, int fact) { if (i <= 1) { return fact; } else { return factorial(i – 1, fact * i); } } 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
13
Tail Recursion Conversion of tail-recursion to iteration easy Create local variable to track most recent result Recreate recursion using for or while loop Get benefits of simplicity without the costs public int factorial(int i, int fact) { if (i <= 1) { return fact; } else { return factorial(i – 1, fact * i); } }
14
public int factorial(int i) { int fact; if (i <= 1) { // Stop recursion } else { fact *= i; // Continue recursion } } Tail Recursion Conversion of tail-recursion to iteration easy Create local variable to track most recent result Recreate recursion using for or while loop Get benefits of simplicity without the costs
15
public int factorial(int i) { int fact = 1; while (i > 1) { fact *= i; i--; } return fact; } Tail Recursion Conversion of tail-recursion to iteration easy Create local variable to track most recent result Recreate recursion using for or while loop Get benefits of simplicity without the costs
16
Recursion Elimination Must first have code that meets criteria Only for tail recursion (recursion at end) Works when method returns 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 for or while loop 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 method returns 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 for or while loop to replace recursion Easier to optimize code & saves call overhead
18
Tail Recursion Elimination
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 Stack replaced with local Stack Method iterates while Stack is not empty Start loop by popping value to be processed
20
public void printInOrder(BNode root) { if (root.hasLeft()) { printInOrder(root.leftChild()); } System.out.println(root.element()); if (root.hasRight()) { printInOrder(root.rightChild()); } } Remove Recursion By Cheating
21
public void printInOrder(BNode root) { Stack stack = // Instantiate stack stack.push(root); while (!stack.isEmpty()) { Object node = stack.pop(); if (node.hasRight()) { push(node.rightChild()); } push(node.element()); if (node.hasLeft()) { push(node.leftChild()); } } } Remove Recursion By Cheating
22
public void printInOrder(BNode root) { Stack stack = // Instantiate stack stack.push(root); while (!stack.isEmpty()) { Object node = stack.pop(); if (node instanceof BNode) { if (node.hasRight()) { push(node.rightChild()); } push(node.element()); if (node.hasLeft()) { push(node.leftChild()); } } else { System.out.println(node); } } } Remove Recursion By Cheating
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 Stack methods 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 1. Create local variable to store current result 2. Use for or while loop to recreate recursion Use recursive step as 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 O BSERVER P ATTERN 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?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.