Recursive Methods Noter ch.2. QUIZ What is the result of the method call foo(4) ? 1.Prints 4...

Post on 11-Jan-2016

214 views 0 download

Transcript of Recursive Methods Noter ch.2. QUIZ What is the result of the method call foo(4) ? 1.Prints 4...

Recursive Methods

Noter ch.2

QUIZ

What is the result of the method call foo(4) ?

1. Prints 4

2. Prints 1

3. Prints 1 2 3 4

4. Prints 4 3 2 1

5. Compiler error: method foo is not allowed to call itself

6. Runtime error: method foo is not allowed to call itself

7. I don’t know

public static void foo(int x) {

System.out.println(x);

if (x>1)

foo(x-1);

}

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

QUIZWhat is the proper recursive definition of the factorial function?

1. n! = n * (n-1)!

2. n! =

3. n! =

4. n! =

5. n! =

6. I don’t know

Factorial function:

n! = 1 * 2 * 3 * ... * (n-1) * n

(n-1)! For n > 11 For n = 1

(n-1)! For n > 1n-1 For n = 1

n*(n-1)! For n > 11 For n = 1

n*(n-1) For n > 1(n-1)! For n = 1

QUIZ

What is the proper method header?

1.public static void factorial()

2.public static int factorial()

3.public static void factorial(int n)

4.public static int factorial(int n)

5. I don’t know

Factorial function:

n! = 1 * 2 * 3 * ... * (n-1) * n

Java method for computing factorial function:

<method header> {

<base case>

<recursive case>

}

QUIZ

What is the proper base case?

1.return 1;

2.return factorial(1);

3.if (n==1) return 1;

4.if (n==1) return factorial(1);

5.return n-1;

6.return factorial(n-1);

7.if (n==1) return n-1;

8.if (n==1) return factorial(n-1);

9. I don’t know

Factorial function:

n! = 1 * 2 * 3 * ... * (n-1) * n

Java method for computing factorial function:

<method header> {

<base case>

<recursive case>

}

QUIZ

What is the proper recursive case?

1.factorial(n-1);

2.factorial(n*n-1);

3.n*factorial(n-1);

4.return factorial(n-1);

5.return factorial(n*n-1);

6.return n*factorial(n-1);

7. I don’t know

Factorial function:

n! = 1 * 2 * 3 * ... * (n-1) * n

Java method for computing factorial function:

<method header>{

<base case>

<recursive case>

}

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)

QUIZ

Which lines should replace to

obtain a correct and recursive

computation of triangle area ?

(for n=4, the area is 10)

1. None of a,b,c,d

2. a

3. b

4. c

5. d

6. More than one of a,b,c,d could be used

7. I don’t know

/* @precondition n>=1 */

public int area(int n) { }

a) return n*(n+1)/2;

b) if (n==1) return 1; else return area(n-1);

c) return n+area(n-1);

d) if (n==1) return 1; else return n+area(n-1);

n

Recursive graphics

• The snowflake is built from 3 Koch lines of order 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 order n-1 each of 1/3 length

Crayon class• State of Crayon object

– Colour– Width (pixel)– Position (coordinates)– Direction (0-360 deg)

• Public methods– Relative changes– move(d): draw line of lenght d (from position in direction to new position)– jump(d): change position without drawing– turn(a): add a degrees to direction– Absolute changes– moveto(x,y):– jumpto(x,y): – turnto(a):

KochLineTest

public class KochLineTest {

public static void main(String[] args) { c = new Crayon(Color.red,1); c.jumpto(50,150); kochLine(4,300); c.turn(120); kochLine(4,300); c.turn(120); kochLine(4,300); c.turn(120); }

private static Crayon c;

private static void kochLine(int order, double len) {...}

}

recursive method kochLine

void kochLine(int order, double len) {

if (order == 0) c.move(len);

else if (order > 0) {

kochLine(order-1,len/3); c.turn(-60);

kochLine(order-1,len/3); c.turn(120);

kochLine(order-1,len/3); c.turn(-60);

kochLine(order-1,len/3);

}

}

QUIZ

Which figures may be

drawn using the method?

1. neither

2. a

3. b

4. a+b

5. I don’t know

private void line(int order, double len, int sign) {

if (order == 0) c.move(len);

else if (order > 0) {

c.turn(sign*60);

line(order-1,len/2,-sign); c.turn(-sign*60);

line(order-1,len/2,sign); c.turn(-sign*60);

line(order-1,len/2,-sign); c.turn(sign*60);

} }a b

Mutual Recursion

• up and down are mutually recursive:

public void down(int n) {

while(n%2==0) n = n/2;

up(n);

}

public void up(int n) {

if (n>1) { n = 3*n+1; down(n); }

}

• It is unknown whether the call down(m) terminates for all m!

QUIZ

Which assertions are correct?

1. Both odd and even always stops

2. odd always stops, but even may loop indefinitely

3. even always stops, but odd may loop indefinitely

4. Both odd and even may loop indefinitely

5. I don’t know

Precondition for both methods: n >= 0

public boolean even(int n) {

if (n==0) return true;

return odd(n-1);

}

public boolean odd(int n) {

if (n==0) return false;

return even(n-1);

}

Using Mutual Recursion

• Problem:– compute the value of arithmetic expressions

such as3 + 4 * 5

(3 + 4) * 51 – (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 recursivelygetExpressionValue

getTermValue

getFactorValue

• An ExpressionTokenizer is used to group input in tokens. A token being a string of digits or one of "+", "-", "*", "/", "(", ")". 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(); while ("+".equals(tokenizer.peekToken()) || "-".equals(tokenizer.peekToken())) { String operator = tokenizer.nextToken(); int value2 = getTermValue(); if ("+".equals(operator)) value = value + value2; else value = value - value2; } return value;}

public int getTermValue() { int value = getFactorValue(); while ("*".equals(tokenizer.peekToken()) || "/".equals(tokenizer.peekToken())) { String operator = tokenizer.nextToken(); int value2 = getFactorValue(); if ("*".equals(operator)) value = value * value2; else value = value / value2; } return value;}

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

QUIZ

Which code could

replace ?

1. Neither a nor b

2. a

3. b

4. a or b

5. I don’t know

public boolean getTermValue() { }

if ("!".equals(tokenizer.peekToken())) { tokenizer.nextToken(); return !getFactorValue();}return getFactorValue();

boolean value = getFactorValue();if ("!".equals(tokenizer.peekToken())) { tokenizer.nextToken(); value = !value;}return value;

a

b

(Part of) syntax diagram for Boolean expression

Random trees and flowers

Random trees and flowers

Recursive trees

• leaf, branch, trunk differ by colors and thickness

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.

class CCrayon

•CCrayon is a variant of Crayon with 2 extra methods:– setColor– setWidth

class TreeTestpublic class TreeTest {

public static void main(String[] args) { c = new CCrayon(); c.jumpto(200,400); c.turn(-90); tree(6,40); } private static CCrayon c;

private static void tree(int order, int len) {...}

private static 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 treepublic void tree(int order, int len) { if (order==0) leaf(len/2); else { int bias = (int) (2*Math.random()); if (order+bias >=6) c.setColor(Color.black); else if (order+bias >=4) c.setColor(Color.gray); else c.setColor(Color.green); c.setWidth(2*order); c.move(len); c.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); c.turn(-BRANCH_ANGLE); } c.turn((BRANCH_ANGLE*(BRANCH_MAX+1))/2.0); c.turn(180); c.jump(len); c.turn(-180); //return pen to base of tree }}

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

Recursion in general: Termination

• Recursive call need not terminatepublic 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 efficientpublic 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;}

QUIZ

How many recursive calls result

in total from the call bin(n,k)

(approximate number)?

1. n

2.

3. n+k

4. nk

5.

6. I don’t know

/* @precondition 0<=k<=n */

public int bin(int n, int k) {

if (k==0 || k==n) return 1;

return bin(n-1,k-1)

+ bin(n-1,k);

}

k=0 k=1 k=2 k=3 k=4 k=5 k=6

n=1 1 1

n=2 1 2 1

n=3 1 3 3 1

n=4 1 4 6 4 1

n=5 1 5 10 10 5 1

n=6 1 6 15 20 15 6 1

k

n

k

n

n2