Lehrstuhl für Medieninformatik Universität Siegen Fakultät IV 9 Rekursion Version: WS 14/15 Fachgruppe Medieninformatik 9.1
9 Rekursion... Motivation: Rekursive Formulierung von Algorithmen führt in vielen Fällen zu sehr effizienten Algorithmenbeschreibung Zusammenhang zwischen Rekursion und Iteration Herausforderungen: Rekursive Algorithmen sind häufig nicht leicht nachvollziehbar bzw. verifizierbar Einordnung der verschiedenen Typen von Rekursionen Literatur: 1. [Ernst] Kapitel 10.6 2. [Gumm] Kapitel 2.8 3. [Herold] Abschnitte 7.5.12 und 19.4.6 (leider fehlen diverse Begriffsbezeichungen) 4. www.mathematik.uni-marburg.de/~vincon/vorlesungen/praktinfo1ws200506/k11 Rekursion.pdf Fachgruppe Medieninformatik 9.2
9.1 Einleitung Bislang kennen wir Iterationen: wiederholtes Durchlaufen einer Folge von Anweisungen Umsetzung durch Schleifen (for, while, do-while) Rekursion ist die direkte oder indirekte Zurückführung eines Problems / einer Funktion / einer zu definierenden Größe auf ein Problem / eine Funktion / eine Größe gleichen Typs. Meist vereinfachen sich bei jeder Rekursion die Parameter des Problems oder der Funktion, indem zum Beispiel die Zahlenwerte kleiner oder Zeichenketten kürzer werden. Eine erste Rekursion wurde bei formalen Sprachen (Abs. 7.4) besprochen: Nonterminale werden häufig durch sich selbst beschrieben Bemerkungen zu Rekursionen: Rekursionen...... können häufig elegant, kompakt und schnell implementiert werden,... sind in bestimmten Fällen äquivalent zur Iteration,... sind meist eine von mehreren Lösungsmöglichkeiten Rekursionen, die nicht abbrechen, führen zu einer Endlosschleife (unendlicher Regress). Fachgruppe Medieninformatik 9.3
9.1 Einleitung... Ein Mops kam in die Küche und stahl dem Koch ein Ei, da nahm der Koch den Löffel und schlug den Mops zu Brei Da kamen viele Möpse und gruben ihm ein Grab und setzten drauf nen Grabstein auf dem geschrieben stand: Ein Mops kam in die Küche und stahl dem Koch ein Ei, da nahm der Koch den Löffel und schlug den Mops zu Brei Da kamen viele Möpse und gruben ihm ein Grab und setzten drauf nen Grabstein auf dem geschrieben stand: Ein Mops kam in die Küche... Fachgruppe Medieninformatik 9.4
9.1 Einleitung... Erinnerung: Vollständige Induktion Vollständige Induktion: Mathematisches Beweistechnik für eine Formel oder Aussage f, die in der Regel von natürlichen Zahlen abhängt Elemente der Induktion sind Induktionsanfang: Beweis der Formel f für 0 oder 1 Induktionsannahme: Formel f gilt für alle i < n N Induktionsschritt: Beweis der Formel für n unter Rückführung auf die Induktionsannahme, d.h. auf Werte f(i) mit i < n Beispiel: Beweis der Summenformel S ( n) n n = i = ( n + 1) Zu beweisen: i= 0 2 0 1 Induktionsanfang: S( 0 ) = = 0 2 Induktionsannahme (IA): Formel gilt bis n 1; n n 1 IA Induktionsschritt: S ( n) = i = n + i i= 0 i= 0 2 ( ) ( n 1) n 2n + n n n( n + 1) = n + 2 = 2 = 2 Fachgruppe Medieninformatik 9.5
9.1 Einleitung... Bemerkungen zur vollständigen Induktion Induktion ist das Schließen vom Speziellen auf das Allgemeine. Beispiel: Ein Naturgesetz aus einzelnen Experimenten ableiten. Methodisch sehr problematisch Deduktion ist das Schließen vom Allgemeinen auf das Spezielle. Beispiel: Aus gegebenen Naturgesetzen soll eine Prognose für ein Einzelexperiment abgeleitet werden. Dazu müssen die Gesetze nur geeignet verknüpft werden. Warum gelingt die Induktion bei natürlichen Zahlen? Sie sind per definitionem so aufgebaut, dass das Induktionsprinzip funktioniert. Man kann die natürlichen Zahlen N so definieren, dass man eine Zahl (1) vorgibt und festlegt, dass mit jeder Zahl n auch die nachfolgende n+1 in N enthalten sein soll. Fachgruppe Medieninformatik 9.6
9.1 Einleitung... Ein einfaches Beispiel: Fakultät Mathematische Definition der Fakultät: Iterativ: Rekursiv: n =1 2 n = i n n ( n ) n = i=1 1 1 n n > 0 = 0 Programme zur Implementierung der Fakultät: Iterativ: int factorial(int n) { int result = 1; int i; for(i=1; i<=n; i++){ result = result i; } return result; } Rekursiv: int factorial(int n) { if( n == 0 ){ // Rekursionsanker return 1; } else { // Rekursionsschritt return n factorial( n-1 ); } } Fachgruppe Medieninformatik 9.7
9.2 Definition von Rekursion und Rekursionstypen Bezug zum Beispiel Bestandteile zur rekursiven Berechnung der Funktion f: Rekursionsanker ( Induktionsanfang): Nicht-rekursive Angabe des Ergebnisse für bestimmte Parameter (hier: 0 = 1) Rekursionsschritt ( Induktionsschritt): Ergebnisberechnung mittels f selbst mit anderem Parameter (hier: n= n (n 1) ) Rekursionstiefe: Anzahl der rekursiven Funktionsaufrufe Bemerkungen: Ohne Rekursionsrichtung, d.h.,,versatz des Parameters im Rekursionsschritt ist die Rekursion nicht definiert. Rekursionsanker und Rekursionsrichtung müssen konsistent sein, sonst führt die Berechnung zu infiniten Regress (,,Endlosschleife ) n n = ( n ) Beispiel: Rekursionsanker für x = 0 und ansteigende Rekursionsrichtung für x > 0 Rekursionen sind häufig, aber nicht zwangsweise, über den natürlichen oder ganzen Zahlen definiert 1 1 n > 0 n = 0 Fachgruppe Medieninformatik 9.8
9.2 Definition von Rekursion und Rekursionstypen... Lineare Rekursion Charakterisierung: Pro Stufe genau ein rekursiver Aufruf zur Definition von f f g = h ( x, f ( r )) r bestimmt den Versatz des Parameters x P P h stellt eine Funktion dar, die einen rekursiv gewonnenen Wert,,verrechnet Bedingung P(x) ist 1 (wahr) genau dann, wenn für x ein Rekursionsanker g(x) definiert ist und f nicht erneut benötigt wird. Weitere Eigenschaften: Es entsteht eine (lineare) Sequenz von Aufrufen Beispiel Fakultät: Aufruf-Sequenz und Rückgabewerte in der Funktion factorial( ) Rekursiver Aufruf fac(3) fac(2) fac(1) fac(0) fac(4) fac(3) fac(2) fac(1) fac(0) Rückgabe: 4 fac(3) 3 fac(2) 2 fac(1) 1 fac(0) 1 Fachgruppe Medieninformatik 9.9
9.2 Definition von Rekursion und Rekursionstypen... Primitive Rekursion Charakterisierung: Lineare Rekursion, bei der das Funktionsargument genau um 1 verschoben wird f g = h ( x, f ( s )) P P = x + 1oder s = x 1, s Weitere Eigenschaften: Kann unmittelbar durch eine Iteration ersetzt werden (und umgekehrt) Beispiel: Fakultät Fachgruppe Medieninformatik 9.10
9.2 Definition von Rekursion und Rekursionstypen... Endrekursion Charakterisierung: Lineare Rekursion, bei der das Funktionsergebnis unmittelbar der Wert eines Rekursionsankers ist f g = f ( r ) P P Beachte: Das Ergebnis des Rekursionsankers g(x) wird über die Aufrufsequenz nur,,zurückgereicht Weitere Eigenschaften: ein rekursiver Aufruf der Funktion pro Stufe kein weiteres Verrechnen des Rückgabewertes Funktionswert entspricht dem Wert eines Rekursionsankers Beispiel: Eine Funktion, die angibt, ob eine Zahl n gerade ist. ( n == 0) n 1 even(n) = even( n 2) sonst Fachgruppe Medieninformatik 9.11
9.2 Definition von Rekursion und Rekursionstypen... Beispiel: Euklidischer Algorithmus Ziel: Berechnung des größten gemeinsamen Teilers ggt zweier Zahlen n, m Euklidischer Algorithmus: Rekursive Berechnung des ggt nach Euklid: ggt m geht auf Euklid (ca. 300 v.chr.) zurück Kommt ohne Kenntnis der Primfaktorzerlegung aus m = n ( m, n) = ggt( m, n m) m < n ggt( m n, n) m > n Beweis: Fall m = n (Rekursionsanker) klar; Fall m n : Sei ohne Beschränkung der Allgemeinheit (o.b.d.a) m < n Dann ist zu zeigen: Alle Teiler von m und n sind auch Teiler von n-m, also ( k teilt m und n) ( k teilt m und n ) (*) k N : m Wenn dies gilt, so ist insbesondere auch der ggt gleich, und die rekursive Formel ist korrekt. Zeige also noch (*). Fachgruppe Medieninformatik 9.12
9.2 Definition von Rekursion und Rekursionstypen... Euklidischer Algorithmus, Beweis (Teil 2): Zeige: k N : k teilt m und n (1) Wenn k die Zahlen m und n teilt, so gibt es Zahlen p, q mit Dann ist aber n-m=(q-p)k und das bedeutet, dass k auch Teiler von n-m ist, was zu beweisen war. (2) ( ) ( k teilt m und n m) m = pk, n=qk, und p<q. Wenn k die Zahlen m und n-m teilt, so gibt es Zahlen p, q mit m = pk, n-m=qk. Dann ist aber (p+q)k = pk + qk = m+(n-m) = n, und das bedeutet, dass k auch Teiler von n ist, was zu beweisen war. Fachgruppe Medieninformatik 9.13
9.2 Definition von Rekursion und Rekursionstypen... Beispiel: Euklidischer Algorithmus (Forts.) Programm-Code: int ggt(int a, int b) { } if ( a == b ) // Rekursionsanker return a; else if ( a < b ) // Rekursionsschritt return ggt( a, b-a ); else return ggt( a-b, b ); Beachte: Dieser rekursive Programmcode ist äußerst kompakt Aufruf-Sequenz für ggt(21, 33): ggt(21,12) ggt(9,12) ggt(9,3) ggt(6,3) ggt(3,3) ggt(21,33) ggt(21,12) ggt(9,12) ggt(9,3) ggt(6,3) ggt(3,3) 3 3 3 3 3 Fachgruppe Medieninformatik 9.14
9.2 Definition von Rekursion und Rekursionstypen... Nichtlineare, baumartige Rekursion Charakterisierung: Der Rekursionsschritt beinhaltet mehr als einen rekursiven Aufruf f g = h ( x, f ( r ),, f ( r ) 1 P k P wobei k > 1 Eigenschaften: es entsteht eine baumförmige Aufrufstruktur, die umso schneller in die Breite wächst, je größer k ist Nachteil: mehrfache, rekursive Funktionsaufrufe belegen viel Arbeitsspeicher Hier: Rekursionstiefe wächst mit der Anzahl der Aufrufe exponentiell Naive Implementierung als rekursiver Algorithmus ist i.a. nicht optimal Prüfe, ob z.b. durch Speicherung von Zwischenergebnissen unnötige mehrfache Berechnungen eingespart werden können. Fachgruppe Medieninformatik 9.15
9.2 Definition von Rekursion und Rekursionstypen... Beispiel: Fibonacci Zahlen Definition: fib 0 = 1 fib x = 0 x = 1 ( x 1) + fib( x 2) x > 1 Erste Fibonacci-Zahlen: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,... Naive Implementierung: int fib( int n ) { if (n == 0) return 0; // Rekursionsanker else if (n == 1) return 1; // Rekursionsanker else { // Rekursionsschritt return fib( n - 1 ) + fib( n - 2 ); } } Fachgruppe Medieninformatik 9.16
9.2 Definition von Rekursion und Rekursionstypen... Beispiel: Fibonacci Zahlen (Forts.) Problem: Mit dieser Implementierung werden Teilergebnisse mehrfach berechnet, z.b. für fib(4) werden fib(2) und fib(0) zwei Mal und fib(1) drei Mal berechnet Aufrufbaum für fib(4) fib(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0) fib(1) fib(0) Anzahl der Aufrufe in Ebene n in etwa 2 n bei Fibonacci (k = 2), im allgemeinen Fall k n für k Aufrufe pro Auswerteebene Abhilfe würde hier also das Speichern von Zwischenergebnissen bringen. Fachgruppe Medieninformatik 9.17
9.2 Definition von Rekursion und Rekursionstypen... Bemerkung: Weitere Rekursionstypen: Direkte Rekursion: Ausschließliche Verwendung der Funktion selbst bei der rekursiven Definition (trifft auf alle bisherigen Beispiele zu) Indirekte Rekursion: Rekursion verwendet weitere Funktion(en): f 1 ( ) ruft f 2 ( ) auf, f 2 ( ) ruft f 1 ( ) auf. Rechnerintern: (Rekursive) Funktionsaufrufe: Kopien von Übergabeparameter und Rücksprungadressen liegen auf dem Stack Rücksprungadresse: Fortsetzungspunkt des aufrufenden Programms Beachte: Iterative Lösung braucht diesen Speicherplatz in der Regel nicht 3 2 3 1 2 Rekursiver Aufruf fac(3) fac(2) fac(1) fac(0) fac(3) fac(2) fac(1) fac(0) 6 2 1 Rückgabe: 3 fac(2) 2 fac(1) 1 fac(0) 1 3 2 3 1 1 3 2 0 1 2 3 3 Fachgruppe Medieninformatik 9.18
9.3 Fraktale als Beispiele rekursiver Funktionen Geometrische Fraktale Ziel: Zeichnen komplexer Muster und Geometrien Beschreibung: Vorgeben einfacher Basisgeometrien (Rekursionsanker), die rekursive durch komplexere Geometrien ersetzt werden (Rekursionsschritt) Wende geometrische Ersetzungsregeln auf entsprechende Teilgeometrien an, so lange bis eine gewünschte Rekursionstiefe erreicht ist Vorteil: Im Gegensatz zu Bildern oder expliziten Geometrien belegen die zur Fraktal-Erstellung benötigten Algorithmen sehr wenig Speicherplatz Nachteil: Die Berechnung der Fraktale ist i.a. zeitaufwändiger als das Einlesen von Bild- oder Geometriedaten aus Dateien Online-Beispiel: http://www.pns-berlin.de/projekte/fraktale/index.html Fachgruppe Medieninformatik 9.19
9.3 Fraktale als Beispiele rekursiver Funktionen... Koch-Kurve : Rekursionstiefe 1 Rekursionstiefe 2 Rekursionstiefe 3 Rekursionstiefe 4 Fachgruppe Medieninformatik 9.20
9.3 Fraktale als Beispiele rekursiver Funktionen... Drachen-Kurve Rekursionstiefe 1 Rekursionstiefe 2 Rekursionstiefe 3 Rekursionstiefe 12 Fachgruppe Medieninformatik 9.21
9.3 Fraktale als Beispiele rekursiver Funktionen... Gewinner des POVRay Fractal Raytracing Contest (2004) Fachgruppe Medieninformatik 9.22
9.4 Zusammenfassung Wichtige Erkenntnisse und Inhalte dieses Abschnitts: Erinnerung an die Beweismethode der vollständigen Induktion Beispiel-Vergleich zwischen Iteration und Rekursion Elemente der Rekursion: Rekursionsanker und Rekursionsschritt, sowie deren Bezug zur Rekursionsrichtung (Gefahr des infiniten Regress) Rekursionstypen: Lineare Rekursion und primitive Rekursion als Spezialfall Endrekursion: Linear, jedoch ohne weitere Verrechnung der Rekursionsankerwerte Baumartige Rekursion: Mehr als ein Funktionsaufruf pro Ebene; i.d.r. ungeeignet zur naiven Implementierung Rechnerintern: Nutzung des Stacks für rekursive Funktionsaufrufe Beispiele aus dem Bereich der Fraktale Fachgruppe Medieninformatik 9.23