Recursive Methods Recursive problem solution Problems that are - - PDF document

recursive methods
SMART_READER_LITE
LIVE PREVIEW

Recursive Methods Recursive problem solution Problems that are - - PDF document

Recursive Methods Recursive problem solution Problems that are naturally solved by recursion Derivative of rational function Recursive Methods Examples: Recursive function: Fibonacci numbers Recursive graphics:


slide-1
SLIDE 1

Recursive Methods

Noter ch.2

Recursive Methods

  • Recursive problem solution

– Problems that are naturally solved by recursion – Derivative of rational function

  • Examples:

– Recursive function: Fibonacci numbers – Recursive graphics: Fractals – Mutual recursion: Expression evaluation – Randomization and recursion: Random plants/trees

  • General aspects

– Termination – Recursion versus iteration: simplicity vs efficiency

Natural Recursion: Derivative of Rational Function

Recursive method calls itself

Recursive Function: Fibonacci Numbers

  • The sequence of Fibonacci numbers is
  • First 10 terms are

– 1, 1, 2, 3, 5, 8, 13, 21, 34, 55

Recursive Function: Fibonacci Numbers

  • Recursive method corresponding to recursive

definition of Fibonacci numbers

public long fib(int n) { if (n <= 1) return 1; else return fib(n - 1) + fib(n - 2); }

Tree Structure of Method Call fib(4)

slide-2
SLIDE 2

Recursive graphics

  • The snowflake is built

from 3 Koch lines of

  • rder 4.
  • The Koch line is

defined recursively

Fractals: Koch lines of order 1-4

  • A line of order 0 is a

straight line

  • A line of order n

consists of 4 lines of

  • rder 3 each of 1/3

length

n>=1

Order n−1 Order n−1 Order n−1 Order n−1 Order

Extending Crayon

  • Crayon class

– dIntProg-opgaver 1.2.1

  • class SnowFlakeCrayon will inherit all

the Crayon methods, and get one new method:

public void snowflake(int order, int len) {...}

  • Application:

SnowflakeCrayon c = new SnowflakeCrayon(Color.red,1); c.jumpto(50,150); c.snowflake(4,300);

SnowFlakeCrayon

public class SnowflakeCrayon extends Crayon { public SnowflakeCrayon(Color c, double w) { super(c,w); } public void snowflake(int order, int len) { kochLine(order,len); turn(120); kochLine(order,len); turn(120); kochLine(order,len); turn(120); } private void kochLine(int order, double len) {...} }

recursive method kochLine

private void kochLine(int order, double len) { if (order == 0) move(len); else if (order > 0) { kochLine(order-1,len/3); turn(-60); kochLine(order-1,len/3); turn(120); kochLine(order-1,len/3); turn(-60); kochLine(order-1,len/3); } } n>=1

Order n−1 Order n−1 Order n−1 Order n−1 Order

Mutual Recursion

  • op and ned are mutually recursive:

public void ned(int n) { while(n%2==0) n = n/2;

  • p(n);

} public void op(int n) { if (n>1) { n = 3*n+1; ned(n); } }

  • It is unknown whether the call ned(m) terminates for all m!
slide-3
SLIDE 3

Using Mutual Recursion

  • Problem:

– compute the value of arithmetic expressions such as 3 + 4 * 5 (3 + 4) * 5 1 – (2 – (3 – (4 – 5)))

  • Precedence rules:

– * and / take precedence over + and – – may overrule using parentheses ( ... )

Syntax diagram for expression

number

Syntax tree for two expressions Mutually recursive methods

  • Implement 3 methods that call each other

recursively

getExpressionValue getTermValue getFactorValue

  • An ExpressionTokenizer is used to group input

in tokens. A token being a string of digits or one

  • f "+", "-", "*", "/", "(", ")". Methods:

peekToken nextToken

public class Evaluator { public Evaluator(String anExpression) { tokenizer = new ExpressionTokenizer(anExpression); } public int getExpressionValue() { ... } public int getTermValue() { ... } public int getFactorValue() { ... } private ExpressionTokenizer tokenizer; } public int getExpressionValue() { int value = getTermValue(); boolean done = false; while (!done) { String next = tokenizer.peekToken(); if ("+".equals(next) || "-".equals(next)) { tokenizer.nextToken(); int value2 = getTermValue(); if ("+".equals(next)) value = value + value2; else value = value - value2; } else done = true; } return value; }

slide-4
SLIDE 4

public int getTermValue() { int value = getFactorValue(); boolean done = false; while (!done) { String next = tokenizer.peekToken(); if ("*".equals(next) || "/".equals(next)) { tokenizer.nextToken(); int value2 = getFactorValue(); if ("*".equals(next)) value = value * value2; else value = value / value2; } else done = true; } return value; }

public int getFactorValue() { int value; String next = tokenizer.peekToken(); if ("(".equals(next)) { tokenizer.nextToken(); value = getExpressionValue(); next = tokenizer.nextToken(); //read ")" } else value = Integer.parseInt(tokenizer.nextToken()); return value; }

Random trees and flowers Random trees and flowers Recursive trees

1 leaf/branch/trunk Order 2 6 5 4 3

  • leaf, branch, trunk differ by colors and thickness

Tree

=

3 smaller trees/branches trunk

Variation by randomization

  • Each tree consists of a trunk and up to

BRANCH_MAX=6 smaller trees

  • Each of the subtrees are drawn with probability

BRANCH_PROB=0.4

  • Subtrees are tilted with angle to neighbor being

BRANCH_ANGLE=13 deg.

Order n−1 Order n−1 Order trunk Order n−1 n>=1 BRANCH_ANGLE leaf

slide-5
SLIDE 5

Extending CCrayon

  • CCrayon is a variant of Crayon with 2 extra

methods: setColor, setWidth

  • class TreeCrayon will inherit all the CCrayon

methods, and get one new public method:

public void tree(int order, int len) {...}

  • Application:

TreeCrayon c = new TreeCrayon(); c.jumpto(200,400); c.turn(-90); c.tree(6,40);

class TreeCrayon

import java.awt.*; public class TreeCrayon extends CCrayon { /** tree draws a random tree * @param order - order of tree * @param len - length of trunk */ public void tree(int order, int len) {...} /** leaf draws maybe(!) a leaf of a random color * @param len - side length of leaf */ private void leaf(int len) { ... } private final static int BRANCH_MAX = 6; private final static int BRANCH_ANGLE = 13; private final static double BRANCH_PROB = 0.4; private final static double LEAF_PROB = 0.3; }

Recursive method tree

public void tree(int order, int len) { if (order==0) leaf(len/2); else { int bias = (int) (2*Math.random()); if (order+bias >=6) setColor(Color.black); else if (order+bias >=4) setColor(Color.gray); else setColor(Color.green); setWidth(2*order); move(len); turn((BRANCH_ANGLE*(BRANCH_MAX-1))/2.0); for (int i = 1 ; i<=BRANCH_MAX ; i = i+1 ) { if (Math.random()<BRANCH_PROB) tree(order-1, len-2); turn(-BRANCH_ANGLE); } turn((BRANCH_ANGLE*(BRANCH_MAX+1))/2.0); turn(180); jump(len); turn(-180); //return pen to base of tree } }

Method leaf

private void leaf(int len) { if (Math.random()<LEAF_PROB) { if (Math.random()<0.5) setColor(Color.red); else setColor(Color.yellow); setWidth(2); turn(-BRANCH_ANGLE/2.0); move(len); turn(BRANCH_ANGLE); move(len); turn(180-BRANCH_ANGLE); move(len); turn(BRANCH_ANGLE); move(len); turn(180-BRANCH_ANGLE/2.0); } }

Recursion in general: Termination

  • Recursive call need not terminate

public void loopingRecursiveMethod() { loopingRecursiveMethod(); }

  • Any reasonable recursive method should have recursion

condition

public long fib(int n) { if (n <= 1) return 1; else return fib(n - 1) + fib(n - 2); } private void kochLine(int order, double len) { if (order == 0) no recursive call else if (order > 0) recursive call } no recursive call recursive call

Thinking recursively vs efficiency

  • Recursive solution may be natural and simple to program

public long fib(int n) { if (n <= 1) return 1; else return fib(n - 1) + fib(n - 2); }

  • But iterative solution may be more efficient

public long iterativeFib(int n) { if (n <= 1) return 1; long fold = 1; long fold2 = 1; long fnew = 1; for (int i = 2; i <= n; i++) { fnew = fold + fold2; fold2 = fold; fold = fnew; } return fnew; }