• Keine Ergebnisse gefunden

Brückenkurs Programmieren Tag 5: Rekursion Christopher Schölzel

N/A
N/A
Protected

Academic year: 2022

Aktie "Brückenkurs Programmieren Tag 5: Rekursion Christopher Schölzel"

Copied!
43
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)Brückenkurs Programmieren Tag 5: Rekursion. Christopher Schölzel Technische Hochschule Mittelhessen. 6. September 2019.

(2) Inhalt. Vorbereitung: Callstack. Rekursion. Nachmittag: Rekursion im Dateisystem und Collections. 2 / 18.

(3) Inhalt. Vorbereitung: Callstack. Rekursion. Nachmittag: Rekursion im Dateisystem und Collections. 3 / 18.

(4) Der Callstack: Speicherbedarf. Bei jedem Funktionsaufruf muss Java sich folgendes behalten: I Rücksprungadresse: Von wo kam der Aufruf? I Argumente: Welche Argumente wurden übergeben? I Lokale Variablen: Was ist der Zustand der zusätzlichen Variablen in der Funktion? I Ergebnisregister: Welcher Wert muss an der Rücksprungadresse eingefügt werden?. 4 / 18.

(5) Der Callstack: Funktionshierarchie Typischer Ablauf eines Programms: I Hauptfunktion main wird aufgerufen I main ruft Funktion A auf I Funktion A ruft Funktion B auf I Funktion B ruft Funktion C auf I .... ⇒ wir müssen alle Informationen für main , A, B, und C speichern ⇒ wir müssen wissen, zu welchem der vielen Aufrufe wir zurückkehren müssen. 5 / 18.

(6) Der Callstack: Aufbau Definition Der (Call-)Stack speichert in einer Programmiersprache die Hierarchie der Funktionsaufrufe mit deren lokalen Parametern und Variablen. I Funktionsaufruf: neuer Stackframe wird oben auf dem Stack angelegt I Rücksprungadresse auf aktuelle Zeile setzen I Parameter mit den übergebenen Argumentwerten füllen I Lokale Variablen mit null initialisieren. I return : oberster Stackframe wird geschlossen I Ergebnisregister beschreiben I aktuelle Zeile auf Rücksprungadresse setzen I Stackframe löschen. zu jeder Zeit gilt: aktiver Funktionsaufruf liegt oben auf dem Stack 6 / 18.

(7) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result:. 7 / 18.

(8) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result:. 7 / 18.

(9) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result:. 7 / 18.

(10) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result: 3.17. 7 / 18.

(11) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res = 26.8. Zeile 9. b=. Zeile 0 Result: 3.17. 7 / 18.

(12) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result: 26.8. 7 / 18.

(13) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b = 26.8. Zeile 0 Result: 26.8. 7 / 18.

(14) Der Callstack: Simulation Die folgenden Folien zeigen den Zustand des Stacks während der Ausführung des angegebenen Programms inklusive Rücksprungadressen und Ergebnisregister. 1 2 3 4 5 6 7 8 9 10 11. double sq(double x) { return x * x; } double bmi(double w, double h) { double res = w / sq(h); return res; } void main() { double b = bmi(85, 1.78); System.out.println(b); }. x = 1.78. Zeile 5. w = 85 h = 1.78 res =. Zeile 9. b=. Zeile 0 Result:. 7 / 18.

(15) Übung: Callstack simulieren Übung an der Tafel: Wir zeichnen den Callstack des folgenden Programms. double sq(double x) { return x * x; } double stoppingDistance(double speed) { double linearTerm = speed * 3 / 10; double quadraticTerm = sq(speed) / 100; return linearTerm + quadraticTerm; } void main() { double d1 = stoppingDistance(50); double d2 = stoppingDistance(70); System.out.println(d2 / d1); }. 8 / 18.

(16) Inhalt. Vorbereitung: Callstack. Rekursion. Nachmittag: Rekursion im Dateisystem und Collections. 9 / 18.

(17) Rekursion: Motivation In der Mathematik ist es oft einfacher, eine Funktion rekursiv zu definieren. Beispiel: ( a ggt(a, b) = ggt(b, a mod b). falls b = 0 sonst. 10 / 18.

(18) Rekursion: Motivation In der Mathematik ist es oft einfacher, eine Funktion rekursiv zu definieren. Beispiel: ( a ggt(a, b) = ggt(b, a mod b). falls b = 0 sonst. Hier taucht die Funktion ggt zur Bestimmung des größten gemeinsamen Teilers zweier Zahlen in ihrer eigenen Definition auf. Trotzdem haben wir eine klare Handlungsanweisung, was zu tun ist: ggt(33, 12) = ggt(12, 33 mod 12) = ggt(12, 9) = ggt(9, 12 mod 9). = ggt(9, 3). = ggt(3, 9 mod 3). = ggt(3, 0). =3 10 / 18.

(19) Rekursion: Definition Definition Eine Funktion nennt man rekursiv, wenn sie sich selbst aufruft. Rekursive Funktionen bestehen immer aus den folgenden Bestandteilen: I mindestens ein Basisfall, in dem die Rekursion abbricht und das Ergebnis fest steht I mindestens ein rekursiver Fall, in dem die Funktion sich selbst mit veränderten („kleineren“) Argumenten aufruft. 11 / 18.

(20) Rekursion: Definition Definition Eine Funktion nennt man rekursiv, wenn sie sich selbst aufruft. Rekursive Funktionen bestehen immer aus den folgenden Bestandteilen: I mindestens ein Basisfall, in dem die Rekursion abbricht und das Ergebnis fest steht I mindestens ein rekursiver Fall, in dem die Funktion sich selbst mit veränderten („kleineren“) Argumenten aufruft Beispiel: GGT int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }. // gcd = greatest common divisor // Basisfall // rekursiver Fall. 11 / 18.

(21) Rekursion und der Stack Was wir mit einer Rechnung auf einem Blatt Papier lösen, lösen Programmiersprachen mit einem Stack. Mathematik. Informatik. ggt(33, 12) = ggt(12, 9) = ggt(9, 3) = ggt(3, 0) =3. a = 3, b = 0 a = 9, b = 3 a = 12, b = 9 a = 33, b = 12. aktueller Aufruf offene Aufrufe. I Jeder Aufruf legt einen neuen Stackframe mit seinen Argumenten oben auf den Stack. I Die aktuellen Argumentwerte stehen im obersten Frame. I Bei einem return wird der Stackframe geschlossen. 12 / 18.

(22) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(23) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(24) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(25) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(26) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(27) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(28) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(29) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result:. 13 / 18.

(30) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(31) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(32) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(33) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(34) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(35) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(36) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(37) Rekursion: Simulation Diese Folie zeigt eine Simulation des Aufrufs gcd(33,12) , inklusive des Stacks mit Rücksprungadressen und dem Ergebnisregister.. 1 2 3 4 5 6 7 8 9. int gcd(int a, int b) { if (b == 0) { return a; } else { int res = gcd(b, a % b); return res; } } System.out.println(gcd(33, 12));. a = 3, b = 0. Zeile 5. a = 9, b = 3. Zeile 5. a = 12, b = 9. Zeile 5. a = 33, b = 12. Zeile 9 Result: 3. 13 / 18.

(38) Aufgabe: Rekursive Summe Implementiere die Funktion sumTo(int) , die die Summe aller Zahlen von 1 bis x nach der folgenden rekursiven Definition errechnet: ( 0 falls x = 0 sumTo(x) = x + sumTo(x − 1) sonst Erinnerung: GGT int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }. // gcd = greatest common divisor // Basisfall // rekursiver Fall. 14 / 18.

(39) Aufgabe: Rekursive Summe Implementiere die Funktion sumTo(int) , die die Summe aller Zahlen von 1 bis x nach der folgenden rekursiven Definition errechnet: ( 0 falls x = 0 sumTo(x) = x + sumTo(x − 1) sonst Erinnerung: GGT int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }. // gcd = greatest common divisor // Basisfall // rekursiver Fall. Bonus: Implementiere eine rekursive Funktion mul(int, int) , die zwei ganze Zahlen a und b multipliziert, ohne den Operators * zu verwenden. 14 / 18.

(40) Aufgabe: Stack zeichnen. An der Tafel:. Wie sieht der Stack und das Ergebnisregister bei dem folgenden Aufruf aus?. int sum6 = sumTo(6);. 15 / 18.

(41) Zusammenfassung Rekursion int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }. Auflösung: Mathematik ggt(33, 12) = ggt(12, 9) = ggt(9, 3) = ggt(3, 0) =3. // Basisfall // Rekursiver Fall. Auflösung: Informatik (Callstack) a = 3, b = 0 a = 9, b = 3 a = 12, b = 9 a = 33, b = 12. aktueller Aufruf offene Aufrufe. 16 / 18.

(42) Inhalt. Vorbereitung: Callstack. Rekursion. Nachmittag: Rekursion im Dateisystem und Collections. 17 / 18.

(43) Mögliche Themen zur Besprechung am Nachmittag Rekursion im Dateisystem I Wie greife ich in Java auf das Dateisystem zu? I Wie kann ich herausfinden, wie viele Dateien sich insgesamt in einem Ordner mit Unterordnern befinden?. Collections I Was mache ich, wenn ich ein Array von variabler Länge brauche? I Wie kann ich am einfachsten alle Duplikate aus einer Liste entfernen? I Welchen Datentyp brauche ich, um die Auftrittshäufigkeit von Worten in einem Text zu bestimmen?. 18 / 18.

(44)

Referenzen

ÄHNLICHE DOKUMENTE

Bunte Fenster und die Maus sind Hilfsmittel, aber es geht auch

Es könnte immer ein Würfelwurf mehr nötig sein.... // die gleichen Anweisungen wie

I double bmi(double, double) sieht nach Rechnung aus I erzeugt aber auch Ausgabe. ⇒ Ausgabe lieber in eigener Funktion

Nachmittag: Java-Objekte erstellen und verwenden.. über einen Index).. über einen Index).. über einen Index).. über einen Index).. über einen Index)... Arrays: Definition,

zwei Punkte erlauben Zahlbereiche anzugeben. – Bsp.: laptop €100..€200 ,

Durch das Definieren einer Funktion gibt man einer oft benötigten Teillösung einen Namen, damit man sie für verschiedene Eingabewerte (Argumente) anwenden kann und den

Fülle das restliche Array, indem du immer den Wert des vorherigen Elements mit 1.01 multiplizierst.. Erinnerung: Arraydefinition

Rekursive Funktionen bestehen immer aus den folgenden Bestandteilen: I mindestens ein Basisfall, in dem die Rekursion abbricht und das Ergebnis fest steht I mindestens ein