R E K U R S I O N

Werbung
R E K U R S I O N
Eine Prozedur ( insbesondere Funktion ) heißt
Teil enthält.
R E K U R S I V, wenn sie sich selbst als
REKURSION ist also WIEDERHOLUNG durch SCHACHTELUNG, die Vorgangsweise ist "TOP - DOWN" ,
d.h. vom ALLGEMEINEN ---> zum ---> BESONDEREN.
ITERATION ist WIEDERHOLUNG durch ANEINANDERREIHUNG, die Vorgangsweise ist "BOTTOM - UP"
, d.h. vom BESONDEREN --> zum --> ALLGEMEINEN.
Jede REKURSIVE Prozedur kann in eine gleichwertige ITERATIVE umgewandelt werden - und
umgekehrt.
Damit Rekursion nicht zu einem unendlichen Regreß führt, bedarf sie eines
REKURSIONSANFANGS; er entspricht der ABBRUCHBEDINGUNG bei Iterationen.
Ein einfaches Beispiel:
Es ist die Summe s(n) aller natürlichen Zahlen von 1 bis n zu berechnen !
s(n) = 1+2+3+4+5+6+ ...... +n
a) ITERATIVE LÖSUNG ( Struktur : SCHLEIFE! )
function summe(n:integer):integer;
var i,s : integer;
begin
s:=0;
for i:=1 to n do
Aufruf vom Hauptprogramm aus mit
s := s + i;
z.B. summe(5);
summe:=s;
end;
b) REKURSIVE LÖSUNG ( Schachtelung )
Die Summe der ersten n Zahlen kann folgendermaßen definiert werden :
s(n) = n + s(n-1)
für
n>0
und nun die Prozedur ( Funktion ) :
Rekursionsanfang :
s(0) = 0
function summe(n:integer):integer;
begin
if n=0 then summe:=0
else summe:=n + summe(n-1);
end;
.
.
( hier ruft sich die Funktion selbst auf!)
Rekursive Programme sind für den Benutzer einfach ( wenn man Rekursion,versteht ! ) ,
iterative für den Computer.
Ein rekursiver Prozeduraufruf erfordert, daß der vorhergehende Aufruf unterbrochen wird, die lokalen Größen müssen bis zur Fortsetzung der unterbrochenen
Prozedur festgehalten werden, ---> dies erfordert Speicherplatz und Zeit.
Ein Problem läßt sich rekursiv lösen, wenn es so in kleinere Teile zerlegbar
ist, daß auf diese ( Teile ) das gleiche Lösungsverfahren anwendbar ist
---> Strategie des DIVIDE and CONQUER : Ein Problem P wird in Teilprobleme
zerlegt, wobei diese dieselbe Struktur aufweisen.
Weitere einfache Beispiele :
- FAKULTÄTSBERECHNUNG :
N ! = 1*2*3*4*5* ... *N = N*(N-1)*(N-2)* ...*2*1
rekursive Definition : n! = n*(n-1)!
Rekursionsanfang
: 0! = 1
- FIBONACCI - Zahlenfolge : f(n) = f(n-1)+f(n-2) mit f(1)=f(2)=1
- FOLGE der MITTELWERTE
: f(n) = (f(n-1)+f(n-2))/2 mit z.B f(1)=0 u. f(2)=6
- GRÖßTER GEMEINSAMER TEILER :
es gilt : ggT(a,b) = ggt(a-b,a)
wenn a > b
(fortgesetzte Subtraktion)
z.B.: ggT(64,36)=ggt(28,36)=ggT(36,28)=ggT(8,28)=ggT(28,8)=ggT(20,8)
=ggT(12,8)=ggT(4,8)=ggT(8,4)=ggT(4,4) ---> ggT(64,36) = 4
1
-------------Programm:
function ggT(a,b
begin
if a = b then
else if a < b
else ggT
end;
: integer):integer;
ggT := a
then ggT := ggT(b,a)
:= ggT(a-b,b)
Veranschaulichung der REKURSION anhand der Zahlenfolge : A(N)=A(N-1)+1
n=1 mit A(0) = 0 (Folge der natürlichen Zahlen )
Rekursion
=
beginnend mit
Schachtelung !
...................................................
.A(N)
.
.
.........................................
.
.
.A(N-1)
.
.
.
.
............................... .
.
.
.
.A(N-2)
. .
.
.
.
.
....................... . .
.
.
.
.
.A(N-3)
. . .
.
.
.
.
.
............... . . .
.
.
.
.
.
.A(N-4) bis
. . . .
.
.
.
.
.
. Rek.anfang . . . .
.
.
.
.
.
............... . . .
.
.
.
.
....................... . .
.
.
.
............................... .
.
.
.
.
.
.
.........................................
.
.
.
...................................................
.........................
.
.
Realisierung in Pascal :
konkretes Beispiel :
function .A(N:integer):integer; .
begin
.
.
if n=0.then A := 0
.
.
.........
.
.else A :=.A(N-1) .+ 1 .
end;
.
.
.
.
.
.........
.
.........................
A(4) = ?
A(4)=4
A(4) =
^ .
^
.
w
^
A(3)=3
i
^ R
.
r
v
^ Ü
.
d
o
^ c
A2)=2
m
^ k
.
^ r
.
^ r
A(1)=1
^ e
.
^ c
.
^ h
.
^ n
.
^ u
.
^ n
.
^ g
.
^
.
^
A(0)=0
A(3)
:
:
A(3)
+
R
e
k
u
r
s
1
=
A(2) + 1
:
:
C
A(2) = A(1) + 1
o
:
m
:
p
g
A(1) = A(0) + 1
u
e
:
t
s
:
e
p
Rekursionsanfang
r
e
:
i
0 (ist bekannt)
chert !
( auf dem STACK )
:
( Teil des RAM )
:
............................ :
i
o
n
s
t
i
e
f
e
Was machen folgende 2 fast idente Programme ?
2
procedure rekdemo1;
uses crt;
procedure rekdemo1;
uses crt;
procedure wasmachich(n : integer);
begin
writeln(n);
wasmachich(n-1);
end;
procedure wasmachichjetzt(n : integer);
begin
wasmachichjetzt(n-1);
writeln(n);
end;
begin
wasmachich(10);
readln;
end.
begin
wasmachichjetzt(10);
readln;
end.
Noch ein Beispiel:
Eine Zeichenfolge, die
durch einen Punkt abgeschlossen
wird, soll in umgekehrter Reihenfolge dargestellt werden
procedure drehe;
var ch : char;
begin
ch:=readkey; write(ch); (Zeichen wird ohne Bestätigung mit RETURN eingelesen)
if ch = '.' then writeln
else begin
drehe;
write(ch)
end;
end;
Ein sehr aktuelles Beispiel
(Die Lehrplanreform - ein Schachtelsatz!).
program der_lehrplan_lebt;
uses crt;
function reform(jahr : integer) : string;
begin
if jahr < 1990 then reform:=´Wie gut war der alte
Lehrplan!!!´
else if jahr=1990 then reform:=´reformierten Lehrplans´
else reform:=´Reform des ´,reform(jahr-1));
end;
begin
writeln(reform(1999));
readln;
end.
3
Herunterladen