2.4    Rekursion 2.4.1    Klassifikation und Beispiele

20
1 2.4 Rekursion 2.4.1 Klassifikation und Beispiele Begriff der Rekursion: allgemein: selbstbezüglicher Verweis, Selbstbezüglichkeit / Selbstähnlichkeit einer Struktur spezielle Bedeutung im Bereich Programmierung: Selbstaufruf einer Prozedur / Funktion Anmerkung: die Theorie rekursiver Funktionen im Sinne der Mathematik baut auch auf Rekursion auf.

description

2.4    Rekursion 2.4.1    Klassifikation und Beispiele. Begriff der Rekursion: allgemein: selbstbezüglicher Verweis, Selbstbezüglichkeit / Selbstähnlichkeit einer Struktur spezielle Bedeutung im Bereich Programmierung: Selbstaufruf einer Prozedur / Funktion - PowerPoint PPT Presentation

Transcript of 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

Page 1: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

1

2.4    Rekursion2.4.1    Klassifikation und Beispiele

Begriff der Rekursion:• allgemein:

selbstbezüglicher Verweis, Selbstbezüglichkeit / Selbstähnlichkeit einer Struktur

• spezielle Bedeutung im Bereich Programmierung:

Selbstaufruf einer Prozedur / Funktion

Anmerkung: die Theorie rekursiver Funktionen im Sinne der Mathematik baut auch auf Rekursion auf.

Page 2: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

2

Beispiele rekursiver Algorithmen:

• größter gemeinsamer Teiler (ggT)

Eingaben a,b ganzzahlig, positiv

algorithmus ggT(a,b: int) int { wenn a=b dann rückgabe a;

wenn b>a dann rückgabe ggT(b,a);

rückgabe ggT(a-b,b) }

Page 3: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

3

• Fakultät einer nat. Zahl (fak) Eingabe n 0, ganzzahlig

algorithmus fak(n: int) int { wenn n=0 dann rückgabe 1 sonst rückgabe n•fak(n-1) }

Page 4: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

4

• Fibonacci-Folge (fibo)

Eingabe n 0, ganzzahlig

algorithmus fibo(n: int) int { wenn (n=0 oder n=1) dann rückgabe n

sonst rückgabe fibo(n-1)+fibo(n-2)

}

Page 5: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

5

Klassifikation (Rekursionstypen):

• endständige Rekursion

Das rekursive Aufrufschema einer Prozedur oder Funktion heißt »endständig«, wenn auf jeder Aufrufebene maximal ein rekursiver Aufruf zur Ausführung gelangt und dieser Aufruf weder von weiteren Anweisungen gefolgt wird (d.h. letzte Anweisung) noch in andere Operationen als Rückgabe (return) eingebunden ist.

Page 6: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

6

• verzweigte (vs. lineare) Rekursion Ein rekursives Aufrufschema heißt verzweigt,

wenn in bestimmten Fällen mehr als ein rekursiver Aufruf zur Ausführung auf einer Aufrufebene gelangt.

Bei maximal einem rekursiven Aufruf pro Ebene heißt das rekursive Aufrufschema linear.

• indirekte (vs. direkte) Rekursion Als indirekte Rekursion wird der Selbstaufruf

einer Prozedur "auf Umwegen" bezeichnet.

Beispiel: Funktion F ruft (in bestimmten Fällen) G, G ruft H und H wiederum F auf.

Page 7: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

7

Vor- und Nachteile der Rekursion

• kompakt, elegant• abstrakt im math.

Sinne• Setzen von Variablen

ohne Zuweisungen (stattdessen: Parameterübergabe).

• schwierig zu handhaben

• hohe Ablaufkomplexi-tät, besonders bei verzweigten Rekur- sionen

• Speicherbedarf für Rekursionskeller

• Effizienznachteil gegenüber Iteration.

Page 8: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

8

Beispiel: "Partitionszahl"

• Definition: Die Partitionszahl P(n) einer natürlichen Zahl n ist die Anzahl der - unabhängig von der Reihenfolge der Summanden - verschiedenen additiven Zerlegungen von n (positive Summanden).

Formal: P(n) := #( { {k1, … , kj} mit n = k1 + … + kj , 0 < ki n} ) Hier ist {k1 ,..,kj } eine Multimenge, d.h. ein

Element darf mehrfach vorkommen.

Page 9: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

9

Problem: gegeben n, berechne P(n) !

Lösung: Rekursion.

Definition: P(n,k) sei die Anzahl der additiven Zerlegungen von n mit positiven Summanden k (hier sei n > 0 und k > 0).

Dann: P(n) = P(n,n) und• P(1,k) = 1• P(n,1) = 1• P(n,k) = P(n,n) für k > n• P(n,n) = P(n,n-1)+1• P(n,k) = P(n,k-1) + P(n-k,k) für k < n

Page 10: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

Beispiel

• Sei n = 5 und k = 3

• P(5,3) = P(5,2) + P(2,2)

10

Page 11: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

11

In Java:

public class Parti {   private static int String2Int(String s)

  { Integer I = new Integer(s);     return I.intValue();   }

  private static int P(int n, int k)   { if ( n == 1 ) return 1;     if ( k == 1) return 1;     if ( k > n ) return P(n,n);     if ( k == n) return P(n,n-1) + 1;     return P(n,k-1) + P(n-k,k);   }   public static void main(String[] args) {     int n = String2Int(args[0]);     System.out.println("------------");     System.out.println("P("+n+") = "+P(n,n));     System.out.println("------------");   } }

Page 12: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

12

Verifikationskriterien:

• Vollständigkeit der Fallunterscheidung

• Korrektheit des Ergebnisses in terminalen Fällen

• Korrektheit der Reduktionsschritte (Fälle)

• Sicherstellung der Reduktion auf den terminalen Fall in endlich vielen Schritten

Page 13: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

13

2.4.2    Umwandlung rekursiver in iterative Verfahren

Beispiel: größter gemeinsamer Teiler rekursiv:algorithmus ggT(a,b: int) int { wenn a=b dann rückgabe a; wenn b>a dann rückgabe ggT(b,a); rückgabe ggT(a-b,b) }

Iterativ: { solange nicht a=b do {wenn b > a dann vertausche(a,b) sonst a := a-b}; rückgabe a }

Page 14: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

14

Beispiel: Fakultät.algorithmus fak(n: int) int { wenn n=0 dann rückgabe 1 sonst rückgabe n•fak(n-1) }

Nicht endständig. Zuerst: Umwandlung in einen Algorithmus mit endständiger Rekursion:

algorithmus fakt(n: int, akku: int) int { wenn n=0 dann rückgabe akku sonst rückgabe fakt(n-1,n•akku) }

(Aufruf mit akku=1).

Page 15: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

15

Endständige Rekursion zur Berechnung der Fakultät:

algorithmus fakt(n: int, akku: int) int

{ wenn n=0 dann rückgabe akku

sonst rückgabe fakt(n-1,n•akku) }

Nun: ein iterativer Algorithmus:

algorithmus faks(n: int) int

{ akku: int;

akku := 1;

solange nicht n=0 führe_aus

{ akku := n•akku; n := n-1 };

rückgabe akku }

Page 16: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

16

Ein anderer iterativer Algorithmus:

algorithmus fakr(n: int) int { akku : int;

akku := 1;

k : int;

k := 0,

solange k < n führe_aus

{ k := k+1; akku := k • akku };

rückgabe akku }

Page 17: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

17

Primitive Rekursion:

Ein allgemeines Schema der linearen Rekursion.

Dient zur Definition einer Funktion 

f: No X Y .

Gegeben:• a: X Y  (Anfangswertfunktion),

• r: No X Y Y (Rekursionsschema).

Dann f definiert durch:

(1)    f(n,x) = a(x),     falls n=0

(2)    f(n,x) = r(n, x, f(n-1,x)),     sonst

Page 18: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

18

• Beispiel: Mit X= No, Y= No, a(x)=1, r(n,x,y)=x•y erhält man die Potenzfunktion f(n,x) = xn.

• Beispiel: Mit X={()}, Y= No, a()=1, r(n,y)=n•y erhält man die Fakultätsfunktion.

• Beispiel: Was für eine Funktion erhält man mit X=Y= R+, a(x)=x/2, r(n,x,y)=1/2(y+(x/y)) ?

Page 19: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

19

public class Iter {

private static int String2Int(String s) { Integer I = new Integer(s); return I.intValue(); }

private static double r(int n, double x, double y) { return 0.5*(y + x/y); }

private static double a(double x) { return x/2; }

private static double iter(int n, double x) { double akku = a(x); int k = 0; while ( k < n ) { System.out.println(k+": "+akku); akku = r(k+1,x,akku); k = k+1; } return akku; }

public static void main(String[] args) {

int x = String2Int(args[0]);

double y = iter(7,x);

System.out.println("-------------------"); System.out.println("Ergebnis: "+y); System.out.println("-------------------"); }}

Page 20: 2.4    Rekursion 2.4.1    Klassifikation und Beispiele

20

• Iterativer Algorithmus für f, definiert durch primitive Rekursion aus a und r :

algorithmus iter(n: int, x: xVal) yVal { akku : yVal; akku := a(x); k : int; k := 0; solange k < n führe_aus { akku := r(k+1,x,akku); k := k+1 }; rückgabe akku }