Unter einer Permutation versteht man die Umordnung einer Zeichenfolge. Permutationen der Zeichenfolge 'ABCD' sind beispielsweise 'CBAD' und 'DCBA'. Gesucht ist ein Algorithmus, mit dem man alle Permutationen einer vorgegebenen Zeichenfolge berechnen kann.
Eine gute Problemlösefähigkeit erreicht man durch
fortgesetzte Übung, welche Erfahrung vermittelt, durch Hartnäckigkeit, welche die eigene
Leistungsfähigkeit bestätigt, aber auch durch Einsatz typischer Problemlösemethoden: was ist gegeben,
was ist gesucht, mache eine Zeichnung, wie kann man das Problem vereinfachen.
Anhand einer Zeichnung erfaßt man die möglichen
Permutationen. Ausgehend von ABCD hält man zunächst A fest und bestimmt dann alle Permutationen von BCD. Den
Vorgang wiederholt man für alle weiteren Buchstaben, die im Ausgangswort enthalten sind. Alle Permutationen von
BCD erhält man nach dem gleichen Schema. Man hält B fest und bildet alle Permutationen von CD, dann hält
man C fest und bildet alle Permutationen von BD, zuletzt hält man D fest und bildet alle Permutationen von BC.
Im Algorithmus muss also unterschieden werden, was festzuhalten und was noch zu permutieren ist. Insgesamt gesehen werden die Permutationen von vier Zeichen durch vier Permutationen zu je drei Zeichen bestimmt, wodurch die rekursive Struktur des Lösungsalgorithmus gegeben ist.
Zur Programmierung einige Hinweise: für den Zugriff auf das i-te Zeichen des Strings Eingabe benutzt man ähnlich wie bei einem Feldzugriff die Schreibweise Eingabe[i]. Mit der Prozedur Delete können ein oder mehrere Zeichen in Strings gelöscht werden. Einzelheiten erfährt man in der Hilfe. Man kann auch gut mit der Copy-Funktion arbeiten.
a) Programmiere den Algorithmus Permutiere.
b) Bestimme seine Komplexität.
Die Zahlen der Folge 0, 1, 1, 2, 3, 5, 8, 13, 21,... bezeichnet man als Fibonacci-Zahlen. Das Bildungsgesetz lautet fib(n) = fib(n-1) + fib(n-2) mit den beiden Anfangswerten fib(0) = 0 und fib(1) = 1. Das Bildungsgesetz hat eine rekursive Struktur, weswegen man leicht eine rekursive Funktion zur Berechnung von Fibonacci-Zahlen programmieren kann.
Stellt man jeden Aufruf der fib-Funktion als Rechteck dar, so erhält man das nebenstehende
Aufrufdiagramm. Über den rechtsgerichteten Pfeilen steht jeweils das Argument, mit dem fib aufgerufen wird.
Die linksgerichteten Pfeile zeigen die Ergebnisse an.
Das Aufrufdiagramm macht deutlich, dass Rekursion Wiederholung durch Schachtelung ist.
Die Komplexität des Berechnungsalgorithmus wird letztlich durch die rekursiven Aufrufe bestimmt. In der
nachfolgenden Tabelle sind in Abhängigkeit von n die Fibonacci-Zahlen und die Zahl der zwecks Berechnung
erforderlichen fib-Aufrufe dargestellt. Man sieht, daß die Zahl der Aufrufe noch stärker wächst
als die Fibonacci-Zahlen.
| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| Fib(n) | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 | 144 | 233 | 377 | 610 |
| Aufrufe(n) | 1 | 1 | 3 | 5 | 9 | 15 | 25 | 41 | 67 | 109 | 177 | 287 | 465 | 753 | 1219 | 1973 |
Die Mathematik liefert für die Fibonacci-Zahlen die Formel:
Sie macht deutlich, dass der Berechnungsalgorithmus exponentielle Komplexität hat.
Lineare Zeitkomplexität erhält man durch die folgende iterative Lösung, konstante
Zeitkomplexität durch Anwendung der Formel.
function fib(n: Integer): Real;
Var i, Fib0, Fib1, FibN: Integer;
begin
If n = 0 then FibN:= 0 else FibN:= 1;
Fib0:= 0; Fib1:= 1;
for i:= 2 to n do begin
FibN:= Fib0 + Fib1;
Fib0:= Fib1;
Fib1:= FibN;
end;
Result:= FibN;
end;
|
|
Rekursion ist Wiederholung durch Schachtelung. Iteration ist Wiederholung durch Aneinanderreihung. |
Rekursion versus Iteration
Es stellt sich die Frage, wann man ein Problem iterativ oder rekursiv lösen sollte. Als Richtschnur kann dabei
gelten, dass Rekursion angewendet werden sollte, wenn
Falls das zugrundeliegende Problem die entsprechende Struktur hat, sind rekursive Lösungen oft besser lesbar und eleganter, aber, wie gezeigt, nicht unbedingt effektiver. Eine rekursive Problemlösung sollte immer dann vermieden werden, wenn eine iterative Lösung offensichtlich ist.