PMG2022/Iteration und Rekursion
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Javascript</language>
== Definition ==
'''Iteration''' bezeichnet das wiederholte Durchlaufen von Anweisungen. Typischerweise wird dabei mitgezählt, wie oft die jeweilige Aktion erledigt wird. Wir kennen dafür die Sprachkonstrukte ''for..to..do, while..do, repeat..until''.
Bei einer '''Rekursion''' erfolgt die Definition eines Problems, einer Funktion oder eines Verfahrens "durch sich selbst". Es handelt sich also wieder um eine Wiederholung, aber <u>ohne Schleife</u>!
Das Ergebnis eines Verfahrens für die Eingabe $x$ wird auf das Ergebnis des gleichen Verfahrens für eine Eingabe $y$ zurückgeführt, das Ergebnis des Verfahrens für die Eingabe $y$ wird wiederum auf das Ergebnis des Verfahrens für eine Eingabe $z$ zurückgeführt, usw.<br>
'''<u>Dabei muss mindestens für einen Wert das Ergebnis des Verfahrens bekannt sein!</u>'''
== Typische Beispiele ==
=== Fakultät ===
==== iterativ ====
<code id="61667decd0120">
function fakultaet(n) {
var ergebnis = 1;
for (var i=1;i<=n;i++) {
ergebnis = ergebnis * i;
}
return ergebnis;
}
</code>
<run id="61667decd02b9">
fakultaet(7);
</run>
oder mit ''while'':
function fakultaet(n) {
var ergebnis = 1;
while (n>1) {
ergebnis = n * ergebnis;
n--
}
return ergebnis;
}
Abarbeitung für n=4:
<table width="20%" border="1" cellpadding="0" cellspacing="2">
<tr>
<td><b><p align="center">n</p></b></td>
<td><b><p align="center">Ergebnis</p></b></td>
</tr>
<tr>
<td><p align="center">-</p></td>
<td><p align="center">1</p></td>
</tr>
<tr>
<td><p align="center">4</p></td>
<td><p align="center">4</p></td>
</tr>
<tr>
<td><p align="center">3</p></td>
<td><p align="center">12</p></td>
</tr>
<tr>
<td><p align="center">2</p></td>
<td><p align="center">24</p></td>
</tr>
<tr>
<td><p align="center">1</p></td>
<td><p align="center">24</p></td>
</tr>
</table>
==== rekursiv ====
<code id="61667decd0194">
function fakultaet_rek(n) {
//ergänzen
}
</code>
<run id="61667decd030f">
fakultaet_rek(4);
</run>
Abarbeitung für n=4:
Aufruf $fak$_$rek(4):=4*fak$_$rek(3)$;
danach "Abstieg in die Rekursionstiefe":
$fak$_$rek(4):=4*fak$_$rek(3)$;
$fak$>_$rek(3):=3*fak$_$rek(2)$;
$fak$_$rek(2):=2*fak$_$rek(1)$;
$fak$>_$rek(1):=1*fak$_$rek(0)$;
Für n=0 liefert das Verfahren den bekannten Wert 1.<br>
Der rekursive "Aufstieg" liefert dann:
$fak$_$rek(1):=1*1=1$;
$fak$_$rek(2):=2*1=2$;
$fak$_$rek(3):=3*2=6$;
$fak$_$rek(4):=4*6=24$;
===== Das Affenmodell =====
Eine schöne Interpretation des rekursiven Prozeduraufrufes finden wir bei W<small>AGENKNECHT</small> in: Rekursionen - Ein didaktischer Zugang mit Funktionen, Dümmler Verlag, Bonn 1994.
<blockquote>
[[Bild:Affenmodell1.gif]]
</blockquote>
''"Der Auftrag, der von außen dem höchsten Oberaffen übergeben wurde, wird von diesem nicht vollständig bearbeitet, sondern in etwas abgeschwächter Form dem untergebenen Affen übergeben. Dieser verhält sich ebenso zu seinem Untergebenen. Der letzte Affe in dieser Hierarchie kann den ihm übergebenen Auftrag erfüllen und dem übergeordneten Affen übergeben. Jeder weitere Affe hat die Pflicht, das Resultat der Erledigung seines Auftrages seinem Auftraggeber zu übergeben. Schließlich kann der Ranghöchste sein Ergebnis abliefern.<br /> Parallelen zu Einrichtungen, Ämtern und Institutionen unserer Gesellschaft sind unbeabsichtigt oder rein zufällig."''
=== Potenz ===
Das Potenzieren wird bekanntermaßen iterativ z.B. so implementiert:
==== iterativ ====
<code id="61667decd01f2">
function potenz(a,b) {
//ergänzen
}
</code>
<run id="61667decd0361">
potenz(3,4);
</run>
==== rekursiv ====
<code id="61667decd024f">
function potenz_rek(a,b) {
// ergänzen
}
</code>
<run id="61667decd03d7">
potenz_rek(3,4);
</run>
== Turtle zeichnet rekursiv - Selbstähnlichkeit ==
Wir betrachten das nachfolgende Grafikobjekt, das wir als Binärbaum bezeichnen wollen. [[Bild:Baum_10.JPG|miniatur|Baum mit n=10]]
Dabei fällt auf, dass jeder Ast wieder ein kleiner Binärbaum ist.<br />
Wir wollen diese ''Selbstähnlichkeit'' zu seiner Beschreibung ausnutzen:<br />
<canvas w=800 h=500></canvas>
<run id="5b753eb475b28">
var c = new Canvas(1);
c.clear(); // Zeichenfläche löschen
var t = new Turtle(1); // neuer Turtle auf Zeichenfläche 1
t.move(400,400);
function baum(n){
if (n>1) { t.forward(n*10);
t.right(45);
baum(n-1);
t.left(90);
baum(n-1);
t.right(45);
t.backward(n*10);
}
else { t.forward(10);
t.backward(10);
}
}
baum(8);
</run>
'''Beschreibung:'''
* Der einfachste Binärbaum (Aufruf: baum(1)) besteht aus einem Stamm.
* Jeder andere Binärbaum besteht aus einem Stamm sowie einem vereinfachten linken und einem vereinfachten rechten Binärbaum.
Wir stellen fest, dass es durchaus sinnvoll sein kann, Objekte mit sich selbst zu beschreiben.<br />
Dazu definiert man den Baum ''mit sich selbst''.
Prozeduren, die mit sich selbst definiert werden, heißen ''rekursive''<sup>1)</sup> ''Prozeduren''.
Rekursionen stellen ein ''leistungsstarkes und universelles Konzept'' zur Problemlösung dar.<br />
<sup>1)</sup> recurrere (lat.): "zurücklaufen"
== Zusammenfassung ==
'''Rekursion bietet sich dann an, wenn man ein gestelltes Problem durch eine Funktion schrittweise in ein etwas einfacheres Problem umwandeln kann.'''
'''typischer Aufbau einer rekursiven Funktion'''
* 1. $if$-Befehl, der das Ende der Selbstaufrufe bestimmt
* 2. ein Aufruf der Funktion selbst
'''Nachteile der Rekursion'''
* 1. Jeder Aufruf kostet Zeit - Rekursion prinzipiell langsamer als Iteration
* 2. jeder Aufruf kostet Speicherplatz - viel Speicher im Stack (Speicherstapel)
Jede Iteration kann als Rekursion formuliert werden, jede Rekursion als Iteration (teilweise schwierig).
Rekursionen werden durch den Compiler bzw. Interpreter der Programmiersprache aufgelöst - der PC-Prozessor arbeitet iterativ.