Educational Objectives You understand how a solution to a recursive problem can be 12. Recursion implemented in Java. You understand how methods are being executed in an execution stack . Mathematical Recursion, Termination, Call Stack, Examples, Recursion vs. Iteration, Lindenmayer Systems 344 345 Mathematical Recursion Recursion in Java: � 1 , if n ≤ 1 n ! = Many mathematical functions can be naturally defined recursively. n · ( n − 1)! , otherwise The means, the function appears in its own definition // POST: return value is n! � public static int fac (int n) { 1 , if n ≤ 1 if (n <= 1) n ! = return 1; n · ( n − 1)! , otherwise else return n * fac (n-1); } 346 347
Infinite Recursion Recursive Functions: Termination As with loops we need is as bad as an infinite loop. . . progress towards termination . . . but even worse: it burns time and memory fac(n): private static void f() { terminates immediately for n ≤ 1 , otherwise the function is called f(); // f() -> f() -> ... stack overflow recusively with < n . } „n is getting smaller with each call.” 348 349 Recursive Functions: Evaluation The Call Stack Example: fac(4) n = 1 n = 1 1! = 1 fac(1) 1 // POST: return value is n! For each method call: n = 2 n = 2 2 · 1! = 2 public static int fac (int n) { push value of the actual parameter on fac(2) 2 the stack if (n <= 1) return 1; n = 3 n = 3 3 · 2! = 6 return n * fac(n-1); // n > 1 work with the upper most value fac(3) 6 } at the end of the call the upper most n = 4 n = 4 4 · 3! = 24 value is removed from the stack fac(4) 24 Out.println(fac(4)) Initialization of the formal argument: n = 4 recursive call with argument n − 1 == 3 350 351
Euclidean Algorithm Euclidean Algorithm in Java � falls b = 0 a, gcd( a, b ) = finds the greatest common divisor gcd( a, b ) of two natural gcd( b, a mod b ) , andernfalls numbers a and b is based on the following mathematical recursion: public static int gcd (int a, int b) { � if (b == 0) a, falls b = 0 Termination: a mod b < b , thus gcd( a, b ) = return a; b is decreased for each recursive gcd( b, a mod b ) , andernfalls else call. return gcd (b, a % b); } 352 353 Fibonacci Numbers Fibonacci Numbers in Java Laufzeit fib(50) takes “forever” because it computes F 48 two times, F 47 3 times, F 46 5 times, F 45 8 times, F 44 13 times, 0 , falls n = 0 F 43 21 times ... F 1 ca. 10 9 times (!) F n := 1 , falls n = 1 public static int fib (int n) { Korrektheit F n − 1 + F n − 2 , falls n > 1 if (n == 0) return 0; und if (n == 1) return 1; Terminierung return fib (n-1) + fib (n-2); // n > 1 sind klar. 0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 . . . } 354 356
Fast Fibonacci Numbers Fast Fibonacci Numbers in Java public static int fib (int n){ if (n == 0) return 0; if (n <= 2) return 1; Idea: int a = 1; // F_1 int b = 1; // F_2 very fast, also for fib(50) Compute each Fibonacci number only once, in the order for (int i = 3; i <= n; ++i){ F 0 , F 1 , F 2 , . . . , F n ! int a_old = a; // F_i-2 Memorize the most recent two numbers (variables a and b )! a = b; // F_i-1 b += a_old; // F_i-1 += F_i-2 -> F_i Compute the next number as a sum of a and b ! } ( F i − 2 , F i − 1 ) − → ( F i − 1 , F i ) return b; } a b 357 358 Recursion and Iteration The Power of Recursion Recursion can always be simulated by Some problems appear to be hard to solve without recursion. With recursion they become significantly simpler. Iteration (loops) Examples: The towers of Hanoi , The n -Queens-Problem, explicit “call stack” (e.g. array) Sudoku-Solver, Expression Parsers, Reversing In- or Output, Often recursive formulations are simpler, sometimes they are less Searching in Trees, Divide-And-Conquer (e.g. sorting) → efficient Informatik II, 359 360
Experiment: The Towers of Hanoi The Towers of Hanoi – Code 0 1 2 Move 4 discs vom 0 to 2 with auxiliary staple 1: Links Mitte Rechts move(4, 0, 1, 2); 361 366 The Towers of Hanoi – Code The Towers of Hanoi – Code move(4, 0, 1, 2); public static void move(int n, int source, int aux, int dest){ == if (n==1){ Out.println("move " + source + " − >" + dest); } else { move(n − 1, source, dest, aux); 1 Move 3 discs from 0 to 1 with auxiliary staple 2: move(1, source, aux, dest); move(3, 0, 2, 1); move(n − 1, aux, source, dest); } 2 Move 1 disc from 0 to 2 } move(1, 0, 1, 2); 3 Move 3 discs from 1 to 2 with auxiliary staple 0 move(3, 1, 0, 2) ; 367 368
Lindenmayer-Systems (L-Systems) Definition and Example Fractals from Strings and Turtles { F , + , − } alphabet Σ c P ( c ) Σ ∗ : finite words over Σ F F + F + production P : Σ → Σ ∗ + + initial word s 0 ∈ Σ ∗ − − F Definition The triple L = (Σ , P, s 0 ) is an L-System. L-Systems have been invented by the Ungarian Biologist Aristid Lindenmayer (1925 – 1989) to model growth of plants. 369 370 The Language Described Turtle Graphics Wörter w 0 , w 1 , w 2 , . . . ∈ Σ ∗ : P ( F ) = F + F + Turtle with position and direction w 0 := s 0 w 0 := F F + F + Turtle understands 3 commands: := P ( w 0 ) := F + F + w 1 w 1 F : move one step + : rotate by 90 de- − : rotate by − 90 := P ( w 1 ) := F + F + + F + F + + forwards � grees � degrees � w 2 w 2 P ( F ) P ( + ) P ( F ) P ( + ) . . trace . . . . Definition P ( c 1 c 2 . . . c n ) := P ( c 1 ) P ( c 2 ) . . . P ( c n ) 371 372
Draw Words! lindenmayer : Main Program word w 0 ∈ Σ ∗ : public static void main(String[] args){ Out.print("Maximal Recursion Depth = "); int depth = In.readInt(); w 1 = F + F + � Turtle t = new Turtle(); produce(t,"F",depth); w = w 0 = F t.show(); } 373 374 lindenmayer: production lindenmayer: replace // POST: recursively iterate over the production of the characters // of a word. // POST: returns the production of c // When recursion limit is reached, the word is "drawn" static String replace (char c){ static void produce (Turtle turtle, String word, int depth){ switch (c) { if (depth > 0) { case ’F’: w = w i → w = w i +1 for (int k = 0; k < word.length(); ++k){ return "F+F+"; produce(turtle, replace(word.charAt(k)), depth − 1); default: } return Character.toString(c); // trivial production c − > c } else { } draw(turtle,word); draw w = w n ! } } } 375 376
The Recursion lindenmayer: draw // POST: draws the turtle graphic interpretation of word F static void draw (Turtle turtle, String word) { produce("F+F+") for (int k = 0; k < word.length(); ++k){ switch (word.charAt(k)) { case ’F’: turtle.forward(1); // move one step forward + + break; F F case ’+’: produce("F+F+") p produce("F+F+") r turtle.left(90); // turn counterclockwise by 90 degrees o p d r o u d u c c e e ( " + ( " " ) break; + " ) } } + + + + + + F F F F } 377 378 L-Systeme: Erweiterungen arbitrary symbols without graphical interpetation arbitrary angles (snowflake) saving and restoring the state of the turtle → plants (bush) Challenge: we are looking forward to your contributions 379
Recommend
More recommend