25
LECTURE 12: ELIMINATING RECURSION CSC 313 – Advanced Programming Topics

Lecture 12: Eliminating Recursion

  • Upload
    yuki

  • View
    31

  • Download
    0

Embed Size (px)

DESCRIPTION

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 - PowerPoint PPT Presentation

Citation preview

Page 1: Lecture 12: Eliminating Recursion

LECTURE 12:ELIMINATING RECURSION

CSC 313 – Advanced Programming Topics

Page 2: 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

Divide-and-conquer algorithms Nearly anything that uses a tree LISP & other functional language

programs Recursion can reduce development

time

Page 3: Lecture 12: Eliminating Recursion

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?

Page 4: Lecture 12: Eliminating Recursion

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?

Page 5: Lecture 12: Eliminating Recursion

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?

Page 6: Lecture 12: Eliminating Recursion

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

Page 7: Lecture 12: Eliminating Recursion

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…

Page 8: Lecture 12: Eliminating Recursion

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

Page 9: Lecture 12: Eliminating Recursion

QuickSort Results

Code same QUICKSORT algorithm 2 ways:1. Recursively2. 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 1.0 1.0Recursiv

e 1.4 1.3 1.1

Page 10: Lecture 12: Eliminating Recursion

What Can We Do?

Convert algorithm to use tail-recursion Make recursive call as last step of

recursion Should directly return result of recursive

callpublic int factorial(int i) { if (i <= 1) { return 1; } else { int result = factorial(i – 1); return result * i; }}

Page 11: Lecture 12: Eliminating Recursion

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

Page 12: Lecture 12: Eliminating Recursion

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

Page 13: Lecture 12: Eliminating 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

public int factorial(int i, int fact) { if (i <= 1) { return fact; } else { return factorial(i – 1, fact * i); }}

Page 14: Lecture 12: Eliminating Recursion

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

Page 15: Lecture 12: Eliminating Recursion

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

Page 16: Lecture 12: Eliminating Recursion

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

Page 17: Lecture 12: Eliminating Recursion

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

Page 18: Lecture 12: Eliminating Recursion

Tail Recursion Elimination NOT ALL ALGORITHMS CAN BE

CONVERTED For some algorithms, recursion may be

required

Page 19: Lecture 12: Eliminating Recursion

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

Page 20: Lecture 12: Eliminating Recursion

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

}

Remove Recursion By Cheating

Page 21: Lecture 12: Eliminating Recursion

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()); }}

}

Remove Recursion By Cheating

Page 22: Lecture 12: Eliminating Recursion

public void printInOrder(BNode<T> root) {Stack stack = // Instantiate stackstack.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

Page 23: Lecture 12: Eliminating Recursion

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

Page 24: Lecture 12: Eliminating Recursion

Recursion Elimination

To do this, algorithm must be tail recursive Rewrite code, if possible, before starting

Conversion of tail-recursion to iteration easy1. Create local variable to store current

result2. 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

Page 25: Lecture 12: Eliminating Recursion

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?