Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung:...

85
Rekursion/Funktionale Programmierung: Einführung und Begriffe 5.1 Einführung und Begriffe 5.2 Beispiele rekursiver Methoden in Java 5.3 Ein Blick auf funktionales Programmieren 5.1 Einführung und Begriffe 5-1

Transcript of Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung:...

Page 1: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Rekursion/Funktionale Programmierung:Einführung und Begriffe

5.1 Einführung und Begriffe5.2 Beispiele rekursiver Methoden in Java5.3 Ein Blick auf funktionales Programmieren

5.1 Einführung und Begriffe 5-1

Page 2: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quersumme

Als einführendes Beispiel sehen wir uns zwei statische Java-Methoden zur Berechnungder Quersumme zweier positiver Zahlen an.

6 → 6

15 → 1 + 5 = 6

789 → 7 + 8 + 9 = 24 → 2 + 4 = 6

5.1 Einführung und Begriffe 5-2

Page 3: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quersumme (iterative Methode)

static int g(int n) {int s = n;while (s > 9) {

int i = s;s = 0;do {

s = s + i%10;i = i / 10;

} while (i > 0);}return s;

}

5.1 Einführung und Begriffe 5-3

Page 4: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quersumme (rekursive Methode)

static int f(int n) {return n <= 9 ? n : f( f(n/10) + n%10 );

}

5.1 Einführung und Begriffe 5-4

Page 5: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quersumme

• Iterative Methode: 10 Zeilen

• Rekursive Methode: 1 Zeile (Weniger als 1 Zeile ist nicht möglich.)

• Rekursion ist eine mächtige Programmiertechnik.

• Wir haben das imperative und das objektorientierte Paradigma kennengelernt.

• In diesem Abschnitt sehen wir uns die Rekursion als Programmiertechnik sowiedas funktionale/deklarative Paradigma an.

5.1 Einführung und Begriffe 5-5

Page 6: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quersumme

Der obige rekursive Algorithmus zur Berechnung der Quersumme lautet alsHaskell-Programm:

f :: Integer -> Integerf n | n <= 9 = n

| otherwise = f(f(n ‘div‘ 10) + (n ‘mod‘ 10))

f 7896

5.1 Einführung und Begriffe 5-6

Page 7: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Partielle und totale Funktionen

Eine partielle Funktionf : A −→ B

ordnet jedem Element x einer Teilmenge Df ⊆ A genau ein Element f (x) ∈ B zu. DieMenge Df heißt Definitionsbereich von f . f ist eine totale Funktion, wenn Df = A gilt.

Beispiel:f : R −→ R, Df = R \ {0}, f (x) = 1

x

Algorithmen können undefinierte Ausdrücke enthalten und müssen nicht in jedem Fallterminieren, d. h.:

Algorithmen berechnen partielle Funktionen!

5.1 Einführung und Begriffe 5-7

Page 8: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Definition von Funktionen

• Wenn der Definitionsbereich einer Funktion endlich ist, lässt sie sich durch Angabealler Funktionswerte in einer Tabelle definieren.

• Beispiel: ∧ : B× B→ B

false false falsefalse true falsetrue false falsetrue true true

5.1 Einführung und Begriffe 5-8

Page 9: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Definition von Funktionen

• In vielen Fällen wird eine Funktion f : A→ B durch einen Ausdruck, der zu jedemElement aus Df genau einen Wert von B liefert, beschrieben.

• Beispiel: max : R× R→ R

max(x , y) ={

x x ≥ yy x < y

= if x ≥ y then x else y fi

5.1 Einführung und Begriffe 5-9

Page 10: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Rekursive Definitionen

Die Funktion f : N −→ N wird durch

f (n) =

1 n = 0,1 n = 1,f(n2)

n ≥ 2, n gerade,f (3n + 1) n ≥ 2, n ungerade.

rekursiv definiert.

5.1 Einführung und Begriffe 5-10

Page 11: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Auswertung von Funktionen

Funktionsdefinitionen können als Ersetzungssysteme gesehen werden. Funktionswertelassen sich aus dieser Sicht durch wiederholtes Einsetzen berechnen. Die Auswertungvon f (3) ergibt

f (3)→ f (10)→ f (5)→ f (16)→ f (8)→ f (4)→ f (2)→ f (1)→ 1.

Terminiert der Einsetzungsprozess stets?

5.1 Einführung und Begriffe 5-11

Page 12: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Formen der Rekursion

• Lineare Rekursion

In jedem Zweig einer Fallunterscheidung tritt die Rekursion höchstens einmal auf.Bei der Auswertung ergibt sich eine lineare Folge von rekursiven Aufrufen.

• Endrekursion

Der Spezialfall einer linearen Rekursion bei dem in jedem Zweig die Rekursion alsletzte Operation auftritt. Endrekursionen können sehr effizient implementiertwerden.

5.1 Einführung und Begriffe 5-12

Page 13: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Formen der Rekursion

• Verzweigende Rekursion oder Baumrekursion

(nk

)=

1 k = 0, k = n,(n − 1k − 1

)+(

n − 1k

)0 < k < n.

• Geschachtelte Rekursion

f (n,m) =

m + 1 n = 0,f (n − 1, 1) n 6= 0,m = 0,f (n − 1, f (n,m − 1)) n 6= 0,m 6= 0.

5.1 Einführung und Begriffe 5-13

Page 14: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Formen der Rekursion

• Verschränkte Rekursion oder wechselseitige Rekursion

Der rekursive Aufruf erfolgt indirekt.

even(n) ={true n = 0,odd(n − 1) n > 0.

odd(n) ={false n = 0,even(n − 1) n > 0.

5.1 Einführung und Begriffe 5-14

Page 15: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fakultät

Definition:

n! ={1 n ≤ 0n · (n − 1)! sonst

Auswertung:

4! = 4 · 3! = 4 · 3 · 2! = 4 · 3 · 2 · 1! = 4 · 3 · 2 · 1 = 24

5.1 Einführung und Begriffe 5-15

Page 16: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fakultätclass Fakultaet {

static long fak(long n) {if (n <= 0)

return 1;else

return n * fak(n-1);}static long f(long n) {

return n <= 0 ? 1 : n * f(n-1);}public static void main(String[] args) {

for (int i = 0; i <= 20; i++) {System.out.println(i + "! = " + fak(i));

}}

}

5.1 Einführung und Begriffe 5-16

Page 17: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge

Definition:

fib(n) =

0 n = 01 n = 1fib(n − 1) + fib(n − 2) n ≥ 2

Funktionswerte:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

5.1 Einführung und Begriffe 5-17

Page 18: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge

Auswertung:

fib 2

fib 1 fib 0

fib 4

fib 3

fib 1fib 2

fib 1 fib 0

fib 3

fib 1fib 2

fib 1 fib 0

fib 5

1

1 1 1

1

00

0

5.1 Einführung und Begriffe 5-18

Page 19: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge

class Fibonacci {static long fib(long n) {

if ((n == 0) || (n == 1))return n;

elsereturn fib(n-1) + fib(n-2);

}public static void main(String[] args) {

for (int i = 0; i <= 20; i++) {System.out.println(i + ": " + fib(i));

}}

}

5.1 Einführung und Begriffe 5-19

Page 20: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge

Die Anzahl der Aufrufe g(n) ist gegeben durch die folgende Rekurrenzgleichung:

g(n) ={1 n = 0, n = 11 + g(n − 1) + g(n − 2) n ≥ 2

Die Funktion g wächst exponentiell. Beispielsweise ist g(5) = 15, vgl. obigesAufrufdiagramm.

Zur Lösung von Rekurrenzgleichungen s. Abschnitt 4.4 in Struckmann/Wätjen.

5.1 Einführung und Begriffe 5-20

Page 21: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge/Dynamische Algorithmen

Am Aufrufdiagramm von fib(5) erkennen wir, dass etliche Funktionswerte mehrfachberechnet werden. Die Idee der dynamischen Algorithmen ist es, Ergebnisse vonBerechnungen zu speichern, so dass die Berechnungen nicht mehrfach durchgeführtwerden müssen.

Die folgende Methode realisiert die Fibonacci-Folge mit einem dynamischenAlgorithmus, indem sie bereits berechnete Funktionswerte in einem Array speichert.Die Array-Elemente werden mit dem Wert −1 vorbesetzt. Die Methode verwendeteine Hilfsmethode.

Implementieren Sie die beiden Algorithmen und vergleichen Sie die Laufzeiten bei derBerechnung einiger Funktionswerte, zum Beispiel fib(40).

5.1 Einführung und Begriffe 5-21

Page 22: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Fibonacci-Folge

static long fib(int n) {if (n==0||n==1) return n;long[] a = new long[n+1];a[0]= 0;a[1]= 1;for (int i=2; i<=n; i++) a[i]=-1;return f(a, n);

}

static long f(long[] a, int n) {if (a[n]>=0) return a[n];return a[n]=f(a,n-1)+f(a,n-2);

}

5.1 Einführung und Begriffe 5-22

Page 23: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Algorithmus von Euklid

Rekursive Version:

ggT(a, b) ={

a, falls b = 0,ggT(b, a mod b), falls b 6= 0.

Auswertung:

ggT(36, 52)→ ggT(52, 36)→ ggT(36, 16)→ ggT(16, 4)→ ggT(4, 0)→ 4

ggT(36, 52) = 4

5.1 Einführung und Begriffe 5-23

Page 24: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Algorithmus von Euklid

class Euklid {static long ggt(long a, long b) {

if (b == 0)return a;

elsereturn ggt(b, a % b);

}public static void main(String[] args) {

System.out.println(ggt(36,52));}

}

5.1 Einführung und Begriffe 5-24

Page 25: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Exponentiationrekursiv:

bn ={1 n = 0b · bn−1 n ≥ 1

iterativ:bn = b · b · ... · b︸ ︷︷ ︸

n-mal

schnell (rekursiv):

bn =

1 n = 0(bn/2)2 n ≥ 1, n gerade

b · bn−1 n ≥ 1, n ungerade

5.1 Einführung und Begriffe 5-25

Page 26: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Schnelle Exponentiation

long exp(long b, long n) {if (n == 0)

return 1;else if (n % 2 == 0) {

long l = exp(b, n / 2);return l * l;

}else

return b * exp(b, n - 1);}

5.1 Einführung und Begriffe 5-26

Page 27: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Summe

Es soll die Summe der Zahlen von a bis b, d. h.∑b

i=a i berechnet werden. Es gilt

b∑i=a

i = a +b∑

i=a+1i.

long sum(long a, long b) {if (a == b)

return b;else

return a + sum(a + 1, b);}

5.1 Einführung und Begriffe 5-27

Page 28: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Skalarprodukt

Es soll das Skalarprodukt der Vektoren a und b rekursiv berechnet werden.

int skalar(int[] a, int[] b, int n) {if (n < 0)

return 0;else {

return a[n] * b[n] + skalar(a, b, n - 1);}

}

5.1 Einführung und Begriffe 5-28

Page 29: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Skalarproduktint skalar(int[] a, int[] b) { // eine ineffiziente Lösung

int l = a.length;if (l == 0)

return 0;else {

int[] aa = new int[l - 1];int[] bb = new int[l - 1];for (int i = 0; i <= l - 2; i++) {

aa[i] = a[i];bb[i] = b[i];

}return a[l - 1] * b[l - 1] + skalar(aa, bb);

}}

5.1 Einführung und Begriffe 5-29

Page 30: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Semantik rekursiv definierter Funktionen 1

(∗) f : N→ N f (n) ={0 n = 0,f (n + 1) n > 0.

• Operationelle Semantik/Ersetzungssystem:

f (0) = 0f (1) = f (2) = f (3) = ...

• Die Auswertung von (∗) terminiert für n > 0 nicht. Daher ist D(f ) = {0} undf (0) = 0.

5.1 Einführung und Begriffe 5-30

Page 31: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Semantik rekursiv definierter Funktionen 2

• Denotationale Semantik/Gleichungssystem: Wir fassen (∗) als Gleichung für eineunbekannte Funktion f auf.

• Für eine partielle Funktion f bedeutet f (k) = f (l), dass die Werte f (k) und f (l)beide undefiniert oder aber definiert und gleich sind.

• Alle Funktionen f : N→ N mit D(f ) = {0} und f (0) = 0 oderD(f ) = {0, 1, 2, ...} = N und

f (0) = 0, f (1) = f (2) = f (3) = ... = a

mit a ∈ N erfüllen die Gleichung (∗). Die operationelle Lösung ist die Lösung mitdem kleinsten Definitionsbereich. Die Lösung von (∗) ist also nicht eindeutig.

5.1 Einführung und Begriffe 5-31

Page 32: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Semantik rekursiv definierter Funktionen 3

a : N× N→ N a(m, n) =

n + 1 m = 0,a(m − 1, 1) m 6= 0, n = 0,a(m − 1, a(m, n − 1)) m 6= 0, n 6= 0.

Outermost: a(1, 1) = a(0, a(1, 0)) = a(1, 0) + 1 = a(0, 1) + 1 = (1 + 1) + 1 = 3Innermost: a(1, 1) = a(0, a(1, 0)) = a(0, a(0, 1)) = a(0, 2) = 3Mixed: a(1, 1) = a(0, a(1, 0)) = a(0, a(0, 1)) = a(0, 1) + 1 = 3

a ist sog. die Ackermann-Funktion. Es gilt:

a(3, 3) = 61, a(4, 4) = 222216

− 3.

5.1 Einführung und Begriffe 5-32

Page 33: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Semantik rekursiv definierter Funktionen 4

f : N× N→ N f (m, n) ={1 m = 0,f (m − 1, f (1, 0)) m 6= 0.

Outermost: f (1, 0) = f (0, f (1, 0)) = 1 (1, 0) ∈ D(f )Innermost: f (1, 0) = f (0, f (1, 0)) = f (0, f (0, f (1, 0))) = ... (1, 0) /∈ D(f )

5.1 Einführung und Begriffe 5-33

Page 34: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Rekursion/Funktionale Programmierung:Beispiele rekursiver Methoden in Java

5.1 Einführung und Begriffe5.2 Beispiele rekursiver Methoden in Java5.3 Ein Blick auf funktionales Programmieren

5.2 Beispiele rekursiver Methoden in Java 5-34

Page 35: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Newton-Verfahren

Es soll rekursiv die Nullstelle der Funktion

f (x) = x3 + 3x + 5

mithilfe des Newton-Verfahrens berechnetwerden:

f ′(x) = 3x2 + 3

xn+1 = xn −f (xn)f ′(xn) –80

–60

–40

–20

0

20

40

60

80

y

–4 –3 –2 –1 1 2 3 4

x

5.2 Beispiele rekursiver Methoden in Java 5-35

Page 36: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Newton-Verfahren

class Newton {double eps;static double f(double x) {

return x*x*x+3*x+5;}static double fs(double x) {

return 3*x*x+3;}Newton(double eps) {

this.eps = eps;}

5.2 Beispiele rekursiver Methoden in Java 5-36

Page 37: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Newton-Verfahrendouble newton(double x) {

System.out.println(x);if (Math.abs(f(x)) <= eps)

return x;else

return newton(x - f(x) / fs(x));}

public static void main(String[] args) {Newton n = new Newton(0.00001);System.out.println(n.newton(1.0));

}

}

5.2 Beispiele rekursiver Methoden in Java 5-37

Page 38: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Intervallschachtelung

Problem: Gegeben seien eine stetige reelle Funktion f und Intervallgrenzena, b ∈ R, a < b. Wir wollen annehmen, dass f (a) und f (b) unterschiedlichesVorzeichen aufweisen. Nach dem Zwischenwertsatz besitzt f im Intervall a ≤ x ≤ bdann wenigstens eine Nullstelle.

Es soll eine Java-Methode

double bisek(double a, double b, double eps)

programmiert werden, die a und b sowie eine Fehlerschranke eps als Eingabenakzeptiert und eine Nullstelle von f im gegebenen Intervall als Ergebnis liefert.

5.2 Beispiele rekursiver Methoden in Java 5-38

Page 39: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Intervallschachtelung

Lösungsidee: Wir halbieren das Intervall schrittweise, sodass die Bedingung, dass fan den Intervallgrenzen Werte mit unterschiedlichen Vorzeichen annimmt, erhaltenbleibt. Damit befindet sich nach jedem Schritt eine Nullstelle von f im aktuellenIntervall. Das Verfahren bricht ab, wenn die Intervallgrenzen nahe genug beieinanderliegen.

5.2 Beispiele rekursiver Methoden in Java 5-39

Page 40: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Intervallschachtelung

static double bisek(double a, double b, double eps) {double m = (a + b) * 0.5;if (Math.abs(a - b) < eps)

return m;else if (f(a) * f(m) > 0)

a = m;else

b = m;return bisek(a, b, eps);

}

5.2 Beispiele rekursiver Methoden in Java 5-40

Page 41: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Rekursionen

• Rekursive Problemlösungen dienen in erster Linie der Einsicht in das Problem.Häufig ist jedoch die rekursive Formulierung auch effizient (z. B. Quicksort) odereine iterative Formulierung nur schwierig zu finden.

• Wir geben jetzt drei Beispiele – einen Geldwechselalgorithmus, die „Türme vonHanoi“ sowie das Acht-Damen-Problem – an, für die rekursive Lösungen auf derHand liegen, iterative aber nur schwer zu finden sind.

5.2 Beispiele rekursiver Methoden in Java 5-41

Page 42: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wechseln eines Geldbetrags

Es soll die Anzahl der Möglichkeiten, ein 10-Cent-Stück in 1-, 2- oder 5-Cent-Stückezu wechseln, berechnet werden. Die gesuchte Anzahl beträgt 10:

• 5+5• 5+2+2+1• 5+2+1+1+1• 5+1+1+1+1+1• 2+2+2+2+2• 2+2+2+2+1+1• 2+2+2+1+1+1+1• 2+2+1+1+1+1+1+1• 2+1+1+1+1+1+1+1+1• 1+1+1+1+1+1+1+1+1+1

5.2 Beispiele rekursiver Methoden in Java 5-42

Page 43: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wechseln eines Geldbetrags

Problem: Es gibt k ≥ 1 verschiedene Münzen mit den Beträgen b0, b1, ... , bk−1 mit0 < b0 < b1 < ... < bk−1. Auf wie viele Arten kann der Betrag a gewechselt werden?

Idee: Wir verwenden einen rekursiven Algorithmus. Wenn die größte Münze nichtverwendet wird, ist die gesuchte Anzahl gleich der Anzahl der Möglichkeiten, denBetrag mit den k − 1 anderen Münzen zu wechseln. Wenn die größte Münze benutztwird, ist die gesuchte Zahl gleich der Anzahl der Möglichkeiten, a − bk−1 mit allen kMünzen zu wechseln.

Beobachtung: Bei jedem Schritt wird entweder die Anzahl der verwendetenMünzsorten oder aber der zu wechselnde Betrag kleiner.

5.2 Beispiele rekursiver Methoden in Java 5-43

Page 44: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wechseln eines Geldbetrags

Als Funktion erhalten wir:

f (a, k) =

0, a < 0 oder k = 0,1, a = 0,f (a, k − 1) + f (a − bk−1, k), sonst.

5.2 Beispiele rekursiver Methoden in Java 5-44

Page 45: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wechseln eines Geldbetragsclass Wechsel {

static int[] b = {1,2,5,10,20,50,100,200};static int wechsel(int a, int k) {

if ((a < 0) || (k == 0))return 0;

else if (a == 0)return 1;

elsereturn wechsel(a, k - 1) + wechsel(a - b[k - 1], k);

}public static void main(String[] args) {

System.out.println(wechsel(10,3));}

}

5.2 Beispiele rekursiver Methoden in Java 5-45

Page 46: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Türme von Hanoi

Problem: Gegeben seien n Scheiben unterschiedlichen Durchmessers, die der Größenach geordnet zu einem Turm geschichtet sind. Die größte Scheibe liegt dabei unten.Der Turm steht auf Platz 1. Unter Verwendung des Hilfsplatzes 3 soll der Turm aufPlatz 2 transportiert werden.

Beim Transport sind die folgenden Bedingungen einzuhalten:

• In jedem Schritt darf nur eine Scheibe – und zwar die oberste eines Turms –bewegt werden.

• Zu keinem Zeitpunkt darf eine größere Scheibe auf einer kleineren liegen.

5.2 Beispiele rekursiver Methoden in Java 5-46

Page 47: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Türme von Hanoi

Beispiel: n = 3

Wir führen die folgenden Schritte aus:

Von 1 nach 2.Von 1 nach 3.Von 2 nach 3.Von 1 nach 2.Von 3 nach 1.Von 3 nach 2.Von 1 nach 2.

5.2 Beispiele rekursiver Methoden in Java 5-47

Page 48: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Türme von Hanoi

Lösungsidee: Wir benutzen den folgenden rekursiven Algorithmus:

• Transportiere n − 1 Scheiben von 1 nach 3.

• Transportiere die verbliebene Scheibe von 1 nach 2.

• Transportiere n − 1 Scheiben von 3 nach 2.

5.2 Beispiele rekursiver Methoden in Java 5-48

Page 49: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Türme von Hanoi

class Hanoi {static void hanoi(int n, int a, int z) {

if (n > 1)hanoi(n - 1, a, 6 - (a + z));

System.out.println("Von " + a + " nach " + z + ".");if (n > 1)

hanoi(n - 1, 6 - (a + z), z);}

public static void main(String[] args) {hanoi(3,1,2);

}}

5.2 Beispiele rekursiver Methoden in Java 5-49

Page 50: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

Problemstellung: Es sind acht Damen so auf einem Schachbrett aufzustellen, dasssie sich gegenseitig nicht bedrohen.

Beispiel:

|D| | | | | | | || | | | | | |D| || | | | |D| | | || | | | | | | |D|| |D| | | | | | || | | |D| | | | || | | | | |D| | || | |D| | | | | |

5.2 Beispiele rekursiver Methoden in Java 5-50

Page 51: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

Lösungsidee:

• Das Spielfeld wird als eindimensionales Feld der Länge 8 gespeichert. Es giltbrett[j] == i genau dann, wenn sich in Zeile i und Spalte j eine Damebefindet.

• Wir schreiben drei Methoden:

◦ ausgabe gibt eine gefundene Lösung auf dem Bildschirm aus.◦ bedroht überprüft, ob die zuletzt gesetzte Dame von einer bereits vorher

platzierten Dame geschlagen werden kann.◦ setze versucht, eine Dame in die nächste Spalte zu stellen. Diese Methode

arbeitet rekursiv von links nach rechts.

5.2 Beispiele rekursiver Methoden in Java 5-51

Page 52: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

/** Gibt das Schachbrett auf dem Bildschirm aus. */

public static void ausgabe(int[] brett) {System.out.println(); // Leerzeile vorherfor (int i=0; i < 8; i++) { // Anzahl der Zeilen

for (int j=0; j < 8; j++) // Anzahl der SpaltenSystem.out.print("|" + ((i == brett[j]) ? ’D’ : ’ ’));

System.out.println("|"); // Zeilenende}System.out.println(); // Leerzeile hinterher

}

Die Methode ausgabe verwendet den Fragezeichen-Operator.

5.2 Beispiele rekursiver Methoden in Java 5-52

Page 53: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

/** Testet, ob die Dame in "spalte" von eineranderen geschlagen werden kann. */

public static boolean bedroht(int[] brett, int spalte) {// Teste zuerst, ob eine Dame in derselben Zeile steht.for (int i=0; i < spalte; i++)

if (brett[i] == brett[spalte])return true;

// Teste dann, ob in der oberen Diagonale eine Dame steht.for (int i = spalte-1, j = brett[spalte]-1; i >= 0; i--,j--)

if (brett[i] == j)return true;

5.2 Beispiele rekursiver Methoden in Java 5-53

Page 54: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

// Teste danach, ob in der unteren Diagonale eine Dame steht.for (int i = spalte-1, j = brett[spalte]+1; i >= 0; i--,j++)

if (brett[i] == j)return true;

// Wenn das Programm hier ist, steht die Dame "frei".return false;

}

Die beiden letzten for-Anweisungen besitzen Initialisierungs- und Update-Listen.

5.2 Beispiele rekursiver Methoden in Java 5-54

Page 55: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

/** Sucht rekursiv eine Lösung des Problems. */

public static boolean setze(int[] brett, int spalte) {// Sind wir fertig?if (spalte == 8) {

ausgabe(brett);return true;

}

5.2 Beispiele rekursiver Methoden in Java 5-55

Page 56: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

// Suche die richtige Position für die neue Dame.for (int i=0; i < 8; i++) {

brett[spalte] = i; // Probiere jede Stelle aus.if (bedroht(brett,spalte)) // Falls Dame nicht frei steht,

continue; // versuche die nächste Stelle.boolean success = setze(brett,spalte+1);if (success) // <-------------

return true; // <-------------}// Wenn das Programm hier angekommen ist,// stecken wir in einer Sackgasse.return false;

}

5.2 Beispiele rekursiver Methoden in Java 5-56

Page 57: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

/** Initialisiert das Schachbrett undruft die Methode "setze" auf. */

public static void main(String[] args) {int[] feld = {0,0,0,0,0,0,0,0}; // Initialisiere Spielfeld.setze(feld,0); // Starte am linken Rand.

}

5.2 Beispiele rekursiver Methoden in Java 5-57

Page 58: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Das Acht-Damen-Problem

• Das obige Programm bricht ab, sobald es eine Lösung gefunden hat.

• Wenn alle Lösungen berechnet werden sollen, müssen lediglich die beiden durch

<-------------

gekennzeichneten Zeilen aus der Methode setze entfernt werden. Das Programmgibt dann 92 Stellungen aus, von denen sich aber etliche nur durch Drehungenoder Spiegelungen unterscheiden.

5.2 Beispiele rekursiver Methoden in Java 5-58

Page 59: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Sortieren

• Wir sehen uns jetzt den Algorithmus „Quicksort“ als Beispiel für einen effizientenrekursiven Algorithmus an.

• Zur Einführung wiederholen wir zunächst kurz das Bubblesort-Verfahren.

• Beide Algorithmen und ihre Eigenschaften werden in der Vorlesung „Algorithmenund Datenstrukturen“ ausführlich besprochen.

5.2 Beispiele rekursiver Methoden in Java 5-59

Page 60: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

BubblesortComparable[] bubbleSort(Comparable[] objs) {

boolean sorted;do {

sorted = true;for (int i = 0; i < objs.length-1; ++i) {

if (objs[i].compareTo(objs[i + 1]) > 0) {Comparable tmp = objs[i];objs[i] = objs[i + 1];objs[i + 1] = tmp;sorted = false;

}}

} while (!sorted);return objs;

}

5.2 Beispiele rekursiver Methoden in Java 5-60

Page 61: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quicksort

Problem: Gegeben ist ein Feld objs, dessen Elemente paarweise vergleichbar sind.Das Teilfeld objs[l] .. objs[r] ist zu sortieren.

Grundidee des Algorithmus:

• Suche ein Pivotelement, z. B. objs[k] mit k = l+r2 .

• Teile das Feld, sodass alle Elemente des linken Felds kleiner als das Pivotelementund alle Elemente des rechten Felds größer oder gleich dem Pivotelement sind.

• Wende das Verfahren rekursiv auf die beiden Teilfelder an.

5.2 Beispiele rekursiver Methoden in Java 5-61

Page 62: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quicksort

Comparable[] quickSort(Comparable[] objs, int l, int r) {if (l < r) {

int i = l,j = r,k = (int) ((l + r) / 2);

Comparable pivot = objs[k];

5.2 Beispiele rekursiver Methoden in Java 5-62

Page 63: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quicksortdo {

while (objs[i].compareTo(pivot) < 0) i++;while (pivot.compareTo(objs[j]) < 0) j--;if (i <= j) {

Comparable t = objs[i];objs[i] = objs[j];objs[j] = t;i++;j--;

}} while (i < j);objs = quickSort(objs, l, j);objs = quickSort(objs, i, r);

}return objs;

}

5.2 Beispiele rekursiver Methoden in Java 5-63

Page 64: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wrapper-Klassen

Problem:

• Primitive Datentypen sind keine Referenztypen.

• Bubblesort und Quicksort können daher in der obigen Form nicht zum Sortierenvon Zahlen verwendet werden.

Lösung:

Man verwende Wrapper-Klassen!

Später: Generics

5.2 Beispiele rekursiver Methoden in Java 5-64

Page 65: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wrapper-Klassen

• Eine Wrapper-Klasse kapselt einen primitiven Wert in einer objektorientierten Hülleund stellt Methoden zum Zugriff auf diesen zur Verfügung. Der Wert kann nichtverändert werden.

• Wrapper-Klassen ermöglichen es, primitive Datentypen und Referenztypeneinheitlich zu behandeln.

• Zu jedem primitiven Datentyp existiert eine Wrapper-Klasse:

Boolean, Char, Byte, Short, Integer, Long, Float, Double, Void.

5.2 Beispiele rekursiver Methoden in Java 5-65

Page 66: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wrapper-Klassen

• Konstruktor mit dem jeweiligen Typ als Parameter:

Integer(int i)Float(float f). . .

• Konstruktor mit einer Zeichenkette als Parameter:

Integer(String s)Float(String s). . .

5.2 Beispiele rekursiver Methoden in Java 5-66

Page 67: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Wrapper-Klassen

• Einige Methoden der Klasse Integer:int intValue()int String toString()int compareTo(Integer anotherInteger)static int parseInt(String s)static int parseInt(String s, int radix)

• Einige Konstante:MIN_VALUEMAX_VALUENaNPOSITIVE_INFINITY

5.2 Beispiele rekursiver Methoden in Java 5-67

Page 68: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Quicksort

int n = ...;Integer[] a = new Integer[n];

a[0] = new Integer(5);a[1] = new Integer(-5);a[2] = new Integer(0);a[3] = new Integer(1);...

Sort.quickSort(a,0,a.length-1);

5.2 Beispiele rekursiver Methoden in Java 5-68

Page 69: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Eine Schnittstelle zum Sortieren

interface Sortieren {Comparable[] sort(Comparable[] objs);

}

class BubbleSortimplements Sortieren {

Comparable[] feld;...

}

class QuickSortimplements Sortieren {

Comparable[] feld;...

}

5.2 Beispiele rekursiver Methoden in Java 5-69

Page 70: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Autoboxing und Unboxing 1

• Um Werte der primitiven Datentypen als Objekte zu behandeln, müssen sie inWrapper-Klassen eingewickelt werden.

• Um z. B. einen int-Wert als Objekt behandeln zu können, muss einInteger-Objekt erzeugt werden:

Integer iWrapper = new Integer(4500)

• Um den eingewickelten Wert auszulesen, muss eine entsprechende Methode derWrapper-Klasse aufgerufen werden:

int iValue = iWrapper.intValue()

• Seit der Version 5 von Java gibt es das Autoboxing und das Unboxing.

5.2 Beispiele rekursiver Methoden in Java 5-70

Page 71: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Autoboxing und Unboxing 2

• Beispiel:

Object obj = 4500; // Autoboxingint i = (Integer) obj; // Unboxing

• Autoboxing und Unboxing gibt es für alle Wrapper-Klassen:

Object obj = 3.14; // Autoboxingdouble d = (Double) obj; // Unboxing

5.2 Beispiele rekursiver Methoden in Java 5-71

Page 72: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Autoboxing und Unboxing 3

int n = ...;Integer[] a = new Integer[n];

a[0] = 5; // Autoboxinga[1] = -5; // Autoboxinga[2] = 0; // Autoboxinga[3] = 1; // Autoboxing...

Sort.quickSort(a,0,a.length-1);

int s = 0;for (int i = 0; i < n; ++i)

s += a[i]; // Unboxing

5.2 Beispiele rekursiver Methoden in Java 5-72

Page 73: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Rekursion/Funktionale Programmierung:Ein Blick auf funktionales Programmieren

5.1 Einführung und Begriffe5.2 Beispiele rekursiver Methoden in Java5.3 Ein Blick auf funktionales Programmieren

5.3 Ein Blick auf funktionales Programmieren 5-73

Page 74: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Funktionen höherer Ordnung

Funktionen können selbst Argumente oder Werte sein. In diesem Fall spricht man vonFunktionen höherer Ordnung oder Funktionalen.

f : (A1 → A2)× A3 → B

g : A→ (B1 → B2)

h : (A1 → A2)→ (B1 → B2)

5.3 Ein Blick auf funktionales Programmieren 5-74

Page 75: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Funktionen höherer Ordnung

Beispiele:

• Summe:b∑

i=af (i)

• Komposition von Funktionen: f ◦ g

• Auswahl zwischen Funktionen: if p then f else g fi

• Bestimmtes Integral:∫ b

af (x) dx

5.3 Ein Blick auf funktionales Programmieren 5-75

Page 76: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Funktionale Algorithmen

Ein Algorithmus heißt funktional, wenn die Berechnungsvorschrift mittels einerSammlung von Funktionen definiert wird. Die Funktionsdefinitionen dürfeninsbesondere Rekursionen und Funktionen höherer Ordnung enthalten.

5.3 Ein Blick auf funktionales Programmieren 5-76

Page 77: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Funktionale Algorithmen

Beispiel:f (0) = 0f (1) = 1f (n) = nf (n − 2)

Wenn wir als Datenbereich die Menge der ganzen Zahlen zugrundelegen, berechnetdieser Algorithmus die Funktion f : Z→ Z mit Df = N und

f (n) =

0 n gerade

n−12∏

i=0(2i + 1) n ungerade

5.3 Ein Blick auf funktionales Programmieren 5-77

Page 78: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Funktionale ProgrammiersprachenProgrammiersprachen, die in erster Linie für die Formulierung funktionalerAlgorithmen gedacht sind, heißen funktional. Funktionale Programmiersprachen sindbeispielsweise

• Lisp, ML, SML,

• Scheme,

• Scala (Erweiterung von Java) und

• Haskell.

Man kann in vielen imperativen Programmiersprachen funktional programmieren –und umgekehrt!

5.3 Ein Blick auf funktionales Programmieren 5-78

Page 79: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Lisp und Scheme

• Lisp wurde Ende der 50er Jahre von John McCarthy entwickelt.

• Im Laufe der Jahre wurden viele Lisp-Dialekte, u. a. Common Lisp und Schemedefiniert.

• Die erste Version von Scheme stammt aus dem Jahre 1975. Autoren waren GuyLewis Steele Jr. und Gerald Jay Sussman.

• Lisp und Scheme werden in der Regel interpretiert, nicht compiliert.

5.3 Ein Blick auf funktionales Programmieren 5-79

Page 80: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Algorithmus von Euklid

Funktional geschrieben hat der

Algorithmus von Euklid

die Form:

ggT(a, 0) = aggT(a, b) = ggT(b, a mod b)

5.3 Ein Blick auf funktionales Programmieren 5-80

Page 81: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Algorithmus von Euklid

Auswertung:

ggT(36, 52)→ ggT(52, 36)→ ggT(36, 16)→ ggT(16, 4)→ ggT(4, 0)→ 4

ggT(36, 52) = 4

5.3 Ein Blick auf funktionales Programmieren 5-81

Page 82: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Scheme: Algorithmus von Euklid

Der funktionale Algorithmus von Euklid lautet als Scheme-Programm:

(define (ggT a b)(if (= b 0)

a(ggT b (remainder a b))))

(ggT 36 52)4

5.3 Ein Blick auf funktionales Programmieren 5-82

Page 83: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Haskell

• Haskell ist eine funktionale Programmiersprache.

• Haskell Brooks Curry (1900–1982) war ein amerikanischer Mathematiker undLogiker.

• Erste Überlegungen zur Programmiersprache Haskell stammen aus dem Jahr 1987.Die Version Haskell 98 wurde 2003 veröffentlicht. Die aktuelle Version Haskell’(Haskell Prime, Haskell 2010) stammt vom Dezember 2009.

• Für Haskell existieren freie Compiler und Interpreter (s. http://haskell.org).

• Es gibt etliche sog. Sprachderivate.Beispiele: Parallel Haskell, Haskell++ (objektorientiert), ...

5.3 Ein Blick auf funktionales Programmieren 5-83

Page 84: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Haskell: Algorithmus von Euklid

Der funktionale Algorithmus von Euklid lautet als Haskell-Programm:

ggT :: Integer -> Integer -> IntegerggT a b | b == 0 = a

| otherwise = ggT b (a ‘mod‘ b)

ggT 36 524

5.3 Ein Blick auf funktionales Programmieren 5-84

Page 85: Rekursion/FunktionaleProgrammierung: · PDF fileRekursion/FunktionaleProgrammierung: BeispielerekursiverMethodeninJava 5.1EinführungundBegriffe 5.2BeispielerekursiverMethodeninJava

Haskell: Quicksort

Der Quicksort-Algorithmus lautet als Haskell-Programm:

qsort [] = []qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger

wheresmaller = [a | a<-xs, a<=x]larger = [a | a<-xs, a>x]

In der Vorlesung „Programmieren für Fortgeschrittene“ erfahren Sie mehr zu diesemThema und können die Sprache „Haskell“ erlernen.

5.3 Ein Blick auf funktionales Programmieren 5-85