Zehn Übungen zu Aufrufstapel, Tracetabelle und Aufrufbaum — vom Begriff bis zur Frage, wie hoch der Stapel wird.
Dein Fortschritt:
0 / 0 Aufgaben
1
Übungsaufgaben
Zehn Übungen zum Klicken, Zuordnen, Rechnen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du nicht weiterkommst, helfen die gestuften Tipps.
A1
Begriffe zum Aufrufstapel
AFB I
Ordne jedem Begriff seine Bedeutung zu, indem du passende Kartenpaare aufdeckst.
Decke zwei Karten auf, die zusammengehören. Mit der Tastatur: Tab zur Karte, Enter aufdecken, Pfeiltasten zum Wandern.
Stapel und Baum sind zwei Sichten auf dieselbe Rekursion: Der Stapel zeigt den Zustand in einem Moment, der Baum den ganzen Ablauf.
Ansatz: Überlege bei jedem Begriff: Geht es um einen Moment, einen einzelnen Aufruf oder den ganzen Ablauf?
Weiter: Die Rekursionstiefe ist eine Zahl — die Höhe des Stapels an seiner höchsten Stelle.
A2
Stapel bei summeQuadrate(4)
AFB I
Betrachtet wird der Aufruf summeQuadrate(4). Gib alle zutreffenden Aussagen an.
static int summeQuadrate(int n) {
if (n == 0) return 0;
return n * n + summeQuadrate(n - 1);
}
Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Auswahl prüfen“.
Aufrufe mit n = 4, 3, 2, 1, 0 — fünf Rahmen. Der zuletzt begonnene Aufruf (n = 0) endet zuerst, der erste (n = 4) zuletzt mit 16 + 14 = 30. Jeder Rahmen hat sein eigenes n.
Ansatz: Zähle alle Werte, die n annimmt — einschließlich 0.
Weiter: Welcher Aufruf beginnt zuletzt? Genau der endet zuerst.
A3
Der Ablauf in Worten
AFB I
Beschreibe den Ablauf von fakultaet(3), indem du die Lücken füllst.
Wort anklicken, dann Lücke anklicken (oder umgekehrt) — mit Tab und Enter geht es genauso. Ein Klick auf eine gefüllte Lücke legt das Wort zurück.
Beim Aufruf fakultaet(3) entsteht ein für n = 3 und wird auf den gelegt. Er auf das Ergebnis von fakultaet(2). Bei n = 1 greift die , der oberste Aufruf liefert 1 als . Danach werden die Rahmen in Reihenfolge wieder entfernt.
Genau dieser Satzbau trägt auch in der Klausur: Rahmen anlegen — warten — Abbruch — Rückgabe — Abbau in umgekehrter Reihenfolge.
Ansatz: Welches Wort steht für den Speicherbereich eines einzelnen Aufrufs?
Weiter: Der Aufrufstapel ist der Ort, der Rahmen das, was dort liegt.
A4
Tracetabelle: Rest durch Abziehen
AFB II
Stelle den Ablauf von rest(17, 5) in der Tracetabelle dar.
static int rest(int a, int b) {
if (a < b) return a;
return rest(a - b, b);
}
Fülle alle Felder aus und prüfe dann. Enter in einem Feld prüft ebenfalls. Wahrheitswerte als wahr oder falsch.
Aufruf
a
b
a < b
Rückgabe
1
17
5
2
5
3
5
4
5
Bei rest steht der Selbstaufruf ganz am Ende (Endrekursion): Jeder Aufruf gibt den Wert des nächsten unverändert zurück, deshalb ist die Rückgabe in allen Zeilen 2. 17 mod 5 = 2.
Ansatz: Jeder Aufruf zieht einmal b ab.
Weiter: Die Rückgabe entsteht im letzten Aufruf und wird nur noch durchgereicht.
A5
Werte und Aufrufe bei t
AFB II
Berechne Werte, Aufrufzahl und Tiefe für die baumrekursive Methode t.
static int t(int n) {
if (n <= 2) return 1;
return t(n - 1) + t(n - 3);
}
Arbeite die Kette Schritt für Schritt ab: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
Ansatz: Berechne erst t(3), dann t(4) und so weiter — jeweils mit schon bekannten Werten.
Weiter: Aufrufe zählen: A(n) = 1 + A(n − 1) + A(n − 3) mit A(n) = 1 für n ≤ 2.
A6
Wer endet zuerst?
AFB II
Beim Aufruf fib(3) entstehen fünf Aufrufe. Bestimme die Reihenfolge, in der sie beendet werden.
Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1fib(1) — aufgerufen von fib(2)
2fib(0) — aufgerufen von fib(2)
3fib(2) — aufgerufen von fib(3)
4fib(1) — aufgerufen von fib(3)
5fib(3) — der erste Aufruf
Links vor rechts, in die Tiefe: fib(2) muss erst ganz fertig sein, bevor fib(3) seinen zweiten Aufruf fib(1) startet. Der erste Aufruf endet immer als letzter.
Ansatz: Zeichne den Aufrufbaum von fib(3).
Weiter: Ein Aufruf endet erst, wenn alle seine Kinder fertig sind.
A7
Negative Zahlen zählen
AFB IIMix
Die Methode arbeitet auf int[] a = {4, -2, 7, -5, -1}; und wird mit zaehleNegative(a, 4) gestartet. Ermittle die gesuchten Werte.
static int zaehleNegative(int[] a, int i) {
if (i < 0) return 0;
int z = zaehleNegative(a, i - 1);
if (a[i] < 0) z++;
return z;
}
Klicke links einen Eintrag an und dann rechts den passenden — es entsteht eine Verbindungslinie. Mit der Tastatur: Enter zum Auswählen, ↑/↓ zum Wandern.
Die Aufrufe laufen von i = 4 bis i = −1 — sechs Rahmen. Gezählt wird erst beim Aufstieg: Der Aufruf mit i = 0 findet 4 (nicht negativ), i = 1 findet −2 und liefert 1, am Ende sind es 3. Index und Wert nicht verwechseln: a[3] ist −5.
Ansatz: Starte unten: Was liefert der Aufruf mit i = −1?
Weiter: Die Zählung wächst beim Rückweg von i = 0 bis i = 4.
A8
Aufrufe sichtbar machen
AFB III
Die Methode soll beim Aufruf summe(3, ...) jeden Aufruf ausgeben — jeden tieferen um zwei Leerzeichen weiter eingerückt, den ersten ganz ohne Einrückung. Ergänze die fehlenden Stellen.
Wähle in jedem Menü den passenden Eintrag und prüfe dann alle auf einmal.
static int summe(int n, String einzug) {
System.out.println(einzug + "summe(" + n + ")");
if (n == 0) return 0;
return n + summe(, );
}
// Start:
summe(3, );
Jeder Rahmen hat sein eigenes einzug. Weil der Selbstaufruf einzug + " " übergibt, ist die Einrückung genau die Rekursionstiefe. Mit " " statt einzug + " " wären alle tieferen Aufrufe gleich weit eingerückt.
Ansatz: Die Einrückung muss mit jeder Stufe um zwei Leerzeichen wachsen.
Weiter: Der erste Aufruf steht ganz links — mit welcher Zeichenkette beginnt man?
A9
Doppelt hält besser?
AFB IIITrick
Analysiere die Methode g: Wie viele Aufrufe von g entstehen insgesamt bei g(5)?
static int g(int n) {
if (n <= 1) return 1;
return g(n - 1) + g(n - 1);
}
Überlege selbst und trage das Ergebnis ein — Enter prüft direkt.
Jeder Aufruf mit n ≥ 2 erzeugt zwei Aufrufe mit n − 1: A(n) = 1 + 2 · A(n − 1), A(1) = 1. Also 3, 7, 15, 31. Die Rekursionstiefe ist trotzdem nur 5 — und g(n) liefert einfach \(2^{n-1}\). Mit return 2 * g(n - 1); hätte ein einziger Aufruf pro Stufe genügt.
Ansatz: Zeichne den Aufrufbaum für g(3) und zähle die Knoten.
Weiter: Beide Selbstaufrufe haben denselben Parameter — der Baum ist voll besetzt.
A10
Wie hoch wird der Stapel?
AFB III
Beurteile für jede Methode, wie viele Rahmen höchstens gleichzeitig auf dem Aufrufstapel liegen, wenn sie mit einer großen Zahl n aufgerufen wird.
Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
1etwa n Rahmen
2etwa log₂ n Rahmen
3ein Rahmen
Der Stapelbedarf hängt von der Tiefe ab, nicht von der Zahl der Aufrufe: fib(n) und g(n) erzeugen exponentiell viele Aufrufe, aber nie mehr als n gleichzeitig. Halbieren führt zu etwa log₂ n Stufen. Schleifen brauchen nur den Rahmen der Methode selbst.
Ansatz: Verfolge den längsten Ast des Aufrufbaums.
Weiter: Viele Aufrufe bedeuten nicht viele gleichzeitig offene Aufrufe.