Rekursion IFB Weiterbildungslehrgang X Informatik Kurs 2: Thema „Rekursion“ 2. 12. 2005 Tobias Selinger 2 Einleitung Was macht man mit einem großen Problem? Rekursion Flugzeugsimulator-Programm ? TS 3 Modularisierung - „Teile und herrsche“ Was macht man mit einem großen Problem? Rekursion Flugzeugsimulator-Programm in Teilprobleme BenutzerOberfläche Level-Editor TS zerlegen SpielSteuerung Kartendatenbank 3D-System Landschaftsgenerator Zerlegung in Teilprobleme? 4 4! = 4• 3•2•1 = 24 Rekursion 5 ! = 5 • 4 • 3 • 2 • 1 = 120 TS Definition: rekursiv lösbar 5 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Beispiel: Zeichne diesen Busch! Ähnliche Teilprobleme ? TS Busch: Teilprobleme 6 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Beispiel 1: Zeichne diesen Busch! linker Teilbusch rechter Teilbusch Ähnliche Teilprobleme: Zeichne Teilbüsche ! Wie ??? TS Level 1 Busch: Teilprobleme 7 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Beispiel 1: Zeichne diesen Busch! TeilTeilbusch busch Teilbusch Teilbusch Level 2 Ähnliche Teilprobleme: Zeichne Teilbüsche ! Wie ??? Ebenso... ! TS Level 1 Busch: Bildungsgesetz 8 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Das rekursive Bildungsgesetz für einen Busch lautet also: Busch = ??? linker (Teil-)Busch Zweig nach links TS rechter (Teil-)Busch Zweig nach rechts Busch: Bildungsgesetz 9 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Das rekursive Bildungsgesetz für einen Busch lautet also: Busch = rechter Zweig + rechter (Teil)-Busch + linker Zweig + linker (Teil)-Busch Beachte: TS Endlos-Rekursion??? linker (Teil-)Busch Zweig nach links rechter (Teil-)Busch Zweig nach rechts Busch: Bildungsgesetz 10 Ein Problem ist rekursiv lösbar, falls man es in Teilprobleme zerlegen kann, die alle • „ähnlich“ zum Gesamtproblem sind • „kleiner“ als das Gesamtproblem sind Rekursion • irgendwann „direkt lösbar“ sind Das rekursive Bildungsgesetz für einen Busch lautet also: Busch = rechter Zweig + rechter (Teil)-Busch + linker Zweig + linker (Teil)-Busch Beachte: TS linker (Teil-)Busch Zweig nach links rechter (Teil-)Busch Zweig nach rechts Wenn ein Teilbusch „klein genug“ ist, gilt er als „abgeschlossen“ (ohne weitere Folgearbeit) ! Ansonsten müsste man endlos weiterzeichnen... Busch: Programmierung 11 Programmierung der Grundstruktur: Rekursion linker (Teil-)Busch procedure busch(laenge: real); begin Eintrittsbedingung if laenge > 10 then with Form1.Turtle1 do begin turnright(20); ??? forwd(laenge); back(laenge); turnleft(40); forwd(laenge); TS back(laenge); turnright(20); end; end; ??? ??? Zweig nach links rechter (Teil-)Busch Zweig nach rechts Busch: Programmierung 12 Programmierung der Grundstruktur: Rekursion linker (Teil-)Busch procedure busch(laenge: real); begin Eintrittsbedingung Zweig nach if laenge > 10 then links with Form1.Turtle1 do begin turnright(20); rechten Zweig zeichnen forwd(laenge); back(laenge); turnleft(40); forwd(laenge); TS back(laenge); turnright(20); end; end; rechter (Teil-)Busch Zweig nach rechts zurück und linken Zweig zeichnen zurück und geradeaus drehen (in Ausgangsposition!) Busch: Programmierung 13 Programmierung der Grundstruktur: Rekursion Ergänzung der rekursiven Aufrufe: TS linker (Teil-)Busch rechter (Teil-)Busch procedure busch(laenge: real); begin Zweig nach Zweig nach if laenge > 10 then links rechts with Form1.Turtle1 do begin turnright(20); rechten Zweig zeichnen forwd(laenge); rechten Teilbusch zeichnen? ??? back(laenge); zurück und turnleft(40); linken Zweig zeichnen forwd(laenge); ??? linken Teilbusch zeichnen? back(laenge); zurück und geradeaus drehen turnright(20); end; end; Busch: Programmierung 14 Programmierung der Grundstruktur: Rekursion Ergänzung der rekursiven Aufrufe: TS linker (Teil-)Busch rechter (Teil-)Busch procedure busch(laenge: real); begin Zweig nach Zweig nach if laenge > 10 then links rechts with Form1.Turtle1 do begin turnright(20); rechten Zweig zeichnen forwd(laenge); rechten Teilbusch zeichnen busch(...................); back(laenge); zurück und turnleft(40); linken Zweig zeichnen forwd(laenge); busch(...................); linken Teilbusch zeichnen back(laenge); zurück und geradeaus drehen turnright(20); end; end; Busch: Programmierung 15 Programmierung der Grundstruktur: Rekursion Ergänzung der rekursiven Aufrufe: TS linker (Teil-)Busch rechter (Teil-)Busch procedure busch(laenge: real); begin Zweig nach Zweig nach if laenge > 10 then links rechts with Form1.Turtle1 do begin turnright(20); rechten Zweig zeichnen forwd(laenge); rechten Teilbusch zeichnen busch(laenge * 0.7); back(laenge); zurück und turnleft(40); linken Zweig zeichnen forwd(laenge); busch(laenge * 0.7); linken Teilbusch zeichnen back(laenge); zurück und geradeaus drehen turnright(20); end; Programmend; Demo! Busch: Aufbau der „Levels“ Rekursion 16 Level 1 TS Busch: Aufbau der „Levels“ Rekursion 17 Level 2 TS Busch: Aufbau der „Levels“ Rekursion 18 Level 3 TS Busch: Aufbau der „Levels“ Rekursion 19 ProgrammDemo! Level ? TS Übungen! 20 Übungen: Spirale und Baum Rekursion Übungen: Entwickeln Sie zunächst das Grundmuster, danach die Einstiegspunkte für rekursive Aufrufe. Vergessen Sie nie die Eintritts-/Abbruchbedingung! Kopieren Sie das Delphi-Projekt „Rekursion graphisch“ und bauen Sie Ihre Prozeduren dort ein! Testen Sie! a) spirale(laenge) erzeugt eine „Spirale“ als geknickte Linie (Winkel jeweils 30°), deren Linienstücke immer kürzer werden. b) baum(laenge) ähnelt dem Busch, hat aber als Grundmuster einen Stamm mit zwei „Knospen“. TS 21 Übungen: Kochkurve und Hutschnur Rekursion c) koch(laenge) erzeugt die berühmte Kochkurve: Das mittlere Drittel einer Strecke wird durch zwei ebenso lange Dreieckseiten ersetzt, dies wird dann auf allen vier Teilstrecken durchgeführt, und wiederum auf deren Teilstrecken... TS d) hutschnur(laenge) ähnelt der Kochkurve, ersetzt das mittlere Drittel aber durch drei Quadratseiten, und setzt dieses Verfahren auf allen Teilstrecken fort. 22 Übungen für Spezialisten: Sierpinski und Drachenkurve Rekursion e) sierpinski(laenge) erzeugt ein gleichseitiges Dreieck, in dessen Ecken halb so große Dreiecke sitzen, in deren Ecken wiederum... TS f) drache(laenge) erzeugt die berühmte Drachenkurve, die sich aus einem geknickten Papierstreifen ergibt: Einen langen Streifen durch Knicken sorgfältig halbieren, die beiden übereinanderliegenden Teilstreifen wieder Knicken ... ... und am Schluss den gesamten Streifen jeweils mit 90°-Knicks auseinanderfalten. Am besten macht man es einmal vor! (Tipp: Verwenden Sie zwei Parameter: drache(laenge, winkel) , wobei der winkel die gewünschte Knickrichtung +/- 90° angibt!) Numerischer Einstieg: Fakultätsfunktion 23 Beispiel 2: Die Fakultät einer Zahl: 4! = 4• 3•2•1 Rekursion Rekursion?? TS = 24 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Test: 3!=? 1!=? Fakultät: Bildungsgesetz 24 Beispiel 2: Die Fakultät einer Zahl: 4! = 4• 3•2•1 = 24 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion Rekursion: TS 5! = 5• Rekursive Formel: n ! = 4! ??? Test: 3!=6 1!=1 Fakultät: Bildungsgesetz 25 Beispiel 2: Die Fakultät einer Zahl: 4! = 4• 3•2•1 = 24 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion Rekursion: TS 5! = 5• Rekursive Formel: n ! = n • 4! (n-1) ! Rekursionsschritt Problem: Was ist 1 ! = ? Test: 3!=6 1!=1 Fakultät: Bildungsgesetz 26 Beispiel 2: Die Fakultät einer Zahl: 4! = 4• 3•2•1 = 24 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion Rekursion: 5! = 5• Rekursive Formel: n ! = n • 4! (n-1) ! , falls n > 1 ist Rekursionsschritt Problem: Test: 3!=6 1!=1 Rekursionbedingung 1! = 1 Start-/Endwert Lösung: Für den Sonderfall n = 1 ist das Teilproblem direkt lösbar, d.h. bei n = 1 erfolgt kein rekursiver Aufruf mehr! Beachte: Jeder rekursive Prozess benötigt eine Rekursionbedingung und einen solchen Start- bzw. Endwert, sonst gingen die rekursiven Aufrufe ins Endlose! TS Rollenspiel! Fakultät: Berechnung mit rekursivem Abstieg... 27 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! TS Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) 4 ! = ??? Fakultät: Berechnung mit rekursivem Abstieg... 28 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! TS Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) 4! = 4• 3! 3! = 3• 2! 2! = 2• 1! 1 ! = ..... Fakultät: Berechnung mit rekursivem Abstieg... 29 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! TS Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) 4! = 4• 3! 3! = 3• 2! 2! = 2• 1! 1!=1 Fakultät: ... und Aufstieg 30 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) 3! = 3• 2! 2! = 2• 1! 1!=1 Phase des rekursiven „Aufstiegs“ (Zusammenbau) TS 4! = 4• 3! 1 2 Fakultät: ... und Aufstieg 31 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) 4! = 4• 3! 3! = 3• 2! 2! = 2• 1! 1!=1 1 Phase des rekursiven „Aufstiegs“ (Zusammenbau) TS 2 6 Fakultät: ... und Aufstieg 32 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 Rekursion 5! = 5• 4! Phase des rekursiven „Abstiegs“ 4! = 4• 3! 3! = 3• 2! 2! = 2• 1! (rekursive Aufrufe) 1!=1 1 Phase des rekursiven „Aufstiegs“ 2 6 (Zusammenbau) 24 120 TS Fakultät: Ab- und Aufstieg 33 Beispiel 2: Die Fakultät einer Zahl: 5 ! = 5 • 4 • 3 • 2 • 1 = 120 5! = 5 • 4! Rekursion = 5 • (4 • 3!) = 5 • (4 • (3 • 2!)) = 5 • (4 • (3 • (2 • 1!))) = 5 • (4 • (3 • (2 • (1)))) = 5 • (4 • (3 • (2))) = 5 • (4 • (6)) = 5 • (24) = 120 TS Phase des rekursiven „Abstiegs“ (rekursive Aufrufe) Phase des rekursiven „Aufstiegs“ (Rückgabe und Zusammenbau der Ergebnisse) Fibonacci (Bildungsgesetz?) 34 Rekursion Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen TS 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Fibonacci (Bildungsgesetz?) 35 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 TS fib(2) = 1 fib(3) = 2 fib(...) = ................... Fibonacci (Bildungsgesetz?) 36 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 TS fib(2) = 1 fib(3) = 2 fib(6) = 5 + 3 = 8 = fib(5) + fib(4) Fibonacci (Startproblem!) 37 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 Bildungsgesetz: TS fib(6) = 5 + 3 = 8 = fib(5) + fib(4) aktuelle Zahl = ??? Fibonacci (Startproblem!) 38 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 Bildungsgesetz: TS fib(6) = 5 + 3 = 8 = fib(5) + fib(4) aktuelle Zahl = letzte Zahl + vorletzte Zahl Fibonacci (Startproblem!) 39 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 Bildungsgesetz: Rekursive Formel: TS fib(6) = 5 + 3 = 8 = fib(5) + fib(4) aktuelle Zahl = letzte Zahl + vorletzte Zahl fib(n) = fib( ... ) + fib( ... ) Fibonacci (Startproblem!) 40 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 = fib(5) + fib(4) Rekursions -Schritt Bildungsgesetz: Rekursive Formel: TS fib(6) = 5 + 3 = 8 aktuelle Zahl = letzte Zahl + vorletzte Zahl fib(n) = fib(n-1) + fib(n-2) Fibonacci (Startproblem!) 41 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 = fib(5) + fib(4) Rekursions -Schritt Bildungsgesetz: TS fib(6) = 5 + 3 = 8 aktuelle Zahl = letzte Zahl + vorletzte Zahl Rekursive Formel: fib(n) = fib(n-1) + fib(n-2) Beachte Problemfall: fib(1) = fib(...) fib(...) ??? + Fibonacci (Startproblem!) 42 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(6) = 5 + 3 = 8 fib(3) = 2 = fib(5) + fib(4) Rekursions -Schritt Bildungsgesetz: aktuelle Zahl = letzte Zahl + vorletzte Zahl Rekursive Formel: fib(n) = fib(n-1) + fib(n-2) Beachte Problemfall: fib(1) = fib(0) fib(-1) ??? + Endlos-Rekursion? Undefiniert? Abhilfe? TS Fibonacci (rekursive Formel) 43 Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursion fib(1) = 1 fib(2) = 1 fib(3) = 2 = fib(5) + fib(4) Rekursions -Schritt Bildungsgesetz: TS fib(6) = 5 + 3 = 8 aktuelle Zahl = letzte Zahl + vorletzte Zahl Rekursive Formel: fib(n) = fib(n-1) + Ausnahme: für n < 3 ist: fib(n) = 1 fib(n-2) Rekursions-Start bzw. -Ende Fibonacci (Funktions-Aufbau) 44 Rekursion Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursive Formel: fib(n) = fib(n-1) + Ausnahme: für n < 3 ist: fib(n) = 1 Aufgabe: Programmiere eine Funktion namens fib, die zur Eingabe n die zugehörige Fibonacci-Zahl liefert! Aufbau der Funktion: TS fib(n-2) Zuweisung des Rückgabewerts an den Funktionsnamen Funktions- EingabeName parameter Typ des Rückgabewerts function fib(n: integer): integer; begin ... fib := ... ... end; Fibonacci (Programmierung) 45 Rekursion Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursive Formel: fib(n) = fib(n-1) + Ausnahme: für n < 3 ist: fib(n) = 1 Aufgabe: Programmiere eine Funktion namens fib, die zur Eingabe n die zugehörige Fibonacci-Zahl liefert! RekursionsBedingung Rekursions -Schritt TS RekursionsAnfang bzw. Ende fib(n-2) function fib(n: integer): integer; begin if ..... then ......... else ......... end; Fibonacci (Programmierung) 46 Rekursion Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursive Formel: fib(n) = fib(n-1) + Ausnahme: für n < 3 ist: fib(n) = 1 Aufgabe: Programmiere eine Funktion namens fib, die zur Eingabe n die zugehörige Fibonacci-Zahl liefert! RekursionsBedingung Rekursions -Schritt TS RekursionsAnfang bzw. Ende fib(n-2) function fib(n: integer): integer; begin if ..... then fib := fib(n-1) + fib(n-2) else ......... end; Rekursions rekursive -Schritt Aufrufe Fibonacci (Programmierung) 47 Rekursion Beispiel 3: Die Fibonacci-Folge beginnt mit den Zahlen 1. 2. 3. 4. 5. 6. 7. 8. 1 1 2 3 5 ... ... ... Rekursive Formel: fib(n) = fib(n-1) + Ausnahme: für n < 3 ist: fib(n) = 1 Aufgabe: Programmiere eine Funktion namens fib, die zur Eingabe n die zugehörige Fibonacci-Zahl liefert! RekursionsBedingung Rekursions -Schritt TS RekursionsAnfang bzw. Ende fib(n-2) function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Rekursions rekursive -Schritt Aufrufe 48 Fibonacci (Aufrufstruktur) Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) TS ........???........ function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 49 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) TS fib(4) + fib(3) ................. function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 50 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) fib(3)+fib(2) ................. TS function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 51 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) fib(3)+fib(2) fib(2)+fib(1) ...... TS ...... function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 52 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) fib(3)+fib(2) fib(2)+fib(1) 1 TS ...... function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 53 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) fib(3)+fib(2) 2 fib(2)+fib(1) 1 TS 1 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 54 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) 3 fib(3)+fib(2) 2 fib(2)+fib(1) 1 1 TS 1 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 55 Aufruf der Fibonacci-Funktion: a := fib(6) Rekursion fib(5) + fib(4) fib(4) + fib(3) 2 3 fib(3)+fib(2) fib(2)+fib(1) 2 fib(2)+fib(1) 1 1 TS 1 1 1 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 56 Aufruf der Fibonacci-Funktion: a := fib(6) fib(5) + fib(4) Rekursion 5 fib(4) + fib(3) 2 3 fib(3)+fib(2) fib(2)+fib(1) 2 fib(2)+fib(1) 1 1 TS 1 1 1 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Fibonacci (Aufrufstruktur) 57 Aufruf der Fibonacci-Funktion: a := fib(6) fib(5) + fib(4) function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Rekursion 5 ................ fib(4) + fib(3) 2 3 fib(3)+fib(2) fib(2)+fib(1) 2 fib(2)+fib(1) 1 1 TS 1 1 1 Fibonacci (Aufrufstruktur) 58 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1) + fib(n-2) else fib := 1 end; Aufruf der Fibonacci-Funktion: a := fib(6) fib(5) + fib(4) Rekursion 5 Beachte: 3 fib(4) + fib(3) 2 3 Verzweigungsfaktor? 2 fib(3)+fib(2) fib(2)+fib(1) fib(2)+fib(1) 2 fib(2)+fib(1) 1 1 TS 1 1 Aufrufstruktur? fib(3) + fib(2) 1 1 1 1 Komplexität? Fibonacci (Aufrufstruktur) 59 function fib(n: integer): integer; begin if n > 2 then fib := fib(n-1)+ fib(n-2) else fib := 1 end; Aufruf der Fibonacci-Funktion: a := fib(6) fib(5) + fib(4) Rekursion 5 Beachte: 3 fib(3) + fib(2) fib(4) + fib(3) 2 3 2 fib(3)+fib(2) fib(2)+fib(1) fib(2)+fib(1) 2 fib(2)+fib(1) 1 1 1 1 1 1 1 1 Durch den zweifachen rekursiven Aufruf von fib entsteht eine (unvollständige) Baumstruktur mit 2-facher Verzweigung! Eine Vergrößerung von n bedeutet daher fast doppelten Aufwand, d.h. die Komplexität n liegt bei etwa 2 . n (asymptotisch: 1,618 ) TS 60 Aufgaben (numerisch) Aufgaben: Entwickeln und testen Sie Funktionen: a) fak zur rekursiven Berechnung der Fakultät einer Zahl Rekursion b) summe_1_bis_n zur Berechnung von 1+2+3+...+n (Tipp: Kopieren und ändern Sie fak entsprechend!) c) fib zur rekursiven Berechnung der Fibonaccizahl d) Bauen Sie bei fib einen Aufrufzähler (globale Variable! warum?) ein, der bei jedem Aufruf von fib inkrementiert wird! e) Zum Vergleich: Programmieren Sie fakiter und fibiter zur iterativen Berechnung von fak und fib, d.h. mit Schleifen anstatt Rekursion! TS 61 Aufgabe: Binomialkoeffizienten f) Eine Funktion mit zwei Eingabewerten: n Rekursion bin(n,k) dient zur Berechnung von Binomialkoeffizienten ( k ) anhand des Pascalschen Dreiecks: ??? ??? TS 62 Aufgabe: Binomialkoeffizienten f) Eine Funktion mit zwei Eingabewerten: n Rekursion bin(n,k) dient zur Berechnung von Binomialkoeffizienten ( k ) anhand des Pascalschen Dreiecks: TS Aufgabe: Permutationen 63 g) Buchstabenrätsel: ZUES = ??? Eine Prozedur soll systematisch alle Permutationen erzeugen! Strategie: Rekursion Z+ perm(UES) U+ perm(ZES) E+ perm(ZUS) S+ perm(ZUE) ... ... ... ZU + perm(ES) ZUE + perm(S) ZUES TS perm(ZUES) ZE + perm(US) ZUS + perm(E) ZUSE ZEU + perm(S) ZEUS ZS + perm(UE) ZES + perm(U) ZESU ZSU + perm(E) ZSUE ZSE + perm(U) ZSEU Tipp: Verwenden Sie zwei Parameter : perm(kopf,rest : string) und den Startaufruf perm(‘‘ , ‘ZUES‘). restlicher Teil bereits permutierter Teil Aufgabe: Ackermann-Funktion 64 h) Ein Beispiel für verschachtelte Rekursion: Rekursion Die Ackermann-Funktion hat 2 Eingabewerte x und y, und wächst extrem schnell! a(x,y) = y+1 , falls x = 0 a(x-1,1) , falls x 0 und y = 0 a(x-1, a(x, y-1)) , sonst Berechne „per Hand“ a(1,1) und a(2, 2) . Programmiere und teste a ! (Für theoretische Informatiker: Die Ackermann-Funktion ist zwar berechenbar, aber nicht primitiv-rekursiv... ) TS Aufgabe: universelle Funktion 65 i) Die universelle Funktion f (x, y, a) kann verschiedene Funktionen berechnen. Rekursion x und y sind die beiden Eingabewerte, und mit a bestimmt man: a = 1: a = 2: a = 3: a > 3: Addieren Multiplizieren Potenzieren ??? x + y , falls a = 1 f (x,y,a) = x, falls a 1 und y = 1 f (x, f (x, y-1, a), a-1) , sonst Berechne „per Hand“ f(4, 3, 2) und f( 2, 3, 3) . Programmiere und teste f ! TS Aufgabe: Türme von Hanoi 66 Rekursion j) Bei den „Türmen von Hanoi“ muss ein Stapel von goldenen Scheiben von einem Startplatz auf einen Zielplatz bewegt werden. Zum Manövrieren gibt es noch einen Ablageplatz, denn es darf niemals eine größere auf eine kleinere Scheibe gelegt werden. Start (1) Ablage (2) Ziel (3) Suchen Sie zunächst das rekursive Prinzip, um das Problem „Bewege einen Turm der Höhe n“ auf ein kleineres Problem zu reduzieren! Entwickeln Sie dann eine rekursive Prozedur hanoi(hoehe, von, nach: integer) , die eine Ausgabe wie z.B. nebenstehend erzeugt! TS (Ein praktischer Trick: 1+2+3 = 6, d.h. die Formel für eine Platznummer lautet immer: „6 – die beiden anderen Platznummern“ . Hilft das ?!) Sammlung rekursiver Probleme 67 Rekursion Eine kleine Sammlung rekursiv lösbarer Probleme: Numerisch: Fakultät, Summe-1-bis-n, Potenz, Fibonacci, Binomialkoeffizienten (Pascalsches Dreieck), universelle Funktion, Ackermann Graphisch: Spirale, Busch, Baum, Kochkurve (Schneeflocke), Hutschnur, Drachenkurve (Papierfaltung), Sierpinski-Dreieck/-Quadrat, Peano-Kurve, Cantor-Staub (zerstückelte Strecke) Textuell: Spiegelung, Permutationen (Buchstabenrätsel), Formale Sprache (Erzeugung anhand Grammatik) Spiel: Zahlenraten, Türme von Hanoi Backtracking: Labyrinth, Acht-Damen- / Springer-Problem, Solitaire (Nimm-Spiel), Spielstrategien Suchen und Sortieren: binäre Suche, Quicksort, Mergesort TS Methodische Zugänge 68 • Problemanalyse: Zerlegung in ähnliche Teilaufgaben • Code-orientiert: a) „Was tut dieses Programm?“ b) Code mit „Auskunftsfunktion“: bei jedem Aufruf wird dieser inkl. aktueller Parameter ausgegeben Rekursion c) Einbau eines Aufruf-Zählers (globale Variable) • Gegenständlich: verschachtelte Kartons oder Matrioschkas (im Innern liegt ein Schatz: nacheinander alle öffnen und danach alle wieder schließen), Papierstreifen falten (Faltrichtung beachten!) • Rollenspiel: Für jeden Aufruf kommt ein weiterer Spieler auf die Bühne, der „seine“ Arbeit demonstriert und ggf. weitere Spieler aufruft. Evtl. Tafelprotokoll. Hilfe: Vorbereitete Aufruf-/Aufgabenzettel. • Visualisierungen: a) Aufrufstruktur mit rekursivem Ab- und Aufstieg TS b) Entwicklung des Aufruf-Stapels („stacks“): Aufbau und Abbau (dynamisches Tafelbild) 69 Rekursion versus Iteration: Bsp. Fakultät Rekursion rekursiv function fak(n: integer): integer; begin if n > 1 then fak := n fak(n-1) else fak := 1; end; Benötigt wird intern ein Stack, um die „unfertigen“ Aufrufe zu speichern. iterativ function fak(n: integer): integer; var f, i: integer; begin f := 1; for i := 2 to n do f := f i; fak := f; end; Benötigt werden hier zwei Variablen: i als Laufvariable für die Schleife, und f als Variable für das Zwischenergebnis, da die „Funktionsvariable“ fak nur auf der linken Seite einer Zuweisung benutzt werden darf! (rechts: rekursiver Aufruf!!) TS 70 Vor- und Nachteile von Rekursion Rekursion Rekursion – pro und contra: + mächtige Methode der Problemzerlegung + elegante „deklarative“ Formulierung der Lösung + flexibel bezüglich der Problemgröße (keine festgelegten Schleifenanzahlen, z.B. bei Permutationen, n-Damen) - nicht sofort zu durchschauen - evtl. unnötig hoher Zeitbedarf (exponentielle Komplexität bei Mehrfachrekursion) (wiederholtes Berechnen von Zwischenergebnissen, z.B. bei fib ) (interner Verwaltungsaufwand: Stack mit begrenzter Größe) TS Literaturverzeichnis und Links 71 Quicksort: Baumann: Informatik für die Sekundarstufe II, Band 2 MUI-Sprache (MU-Problem): Hofstadter: Gödel, Escher, Bach (dtv 1991) Rekursion ETH: http://www.ite.ethz.ch/education/id1/vortraege/rekursion.pdf Downloads (Word, PDF) zu "Rekursives Programmieren": http://educeth.ethz.ch/informatik/leitprog/rekursion http://educeth.ethz.ch/informatik/vortraege/backtracking Rekursion Backtracking anschaulich: Über Fragen, Hinweise, Korrekturen würde ich mich freuen: [email protected] TS