Objektorientierte Programmierung VL: Prof. Dr. Marco Block

Werbung
Objektorientierte Programmierung
VL: Prof. Dr. Marco Block-Berlitz - Freie Universität Berlin
Proinformatik III
Text: Hinnerk van Bruinehsen - Grafiken: Jens Fischer
powered by SDS.mint
SoSe 2011
1
Teil I
1. Tag
1
Einführung in die Algorithmik
1.1
Definition Algorithmus
Allgemein lässt sich der Begriff wie folgt charakterisieren:
• Es ist eine Menge von Regeln, die ein Problem löst.
• Eine Menge von Anweisungen, die garantiert in einer endlichen Anzahl von Schritten (Terminierung), eine korrekte Lösung für jedes Beispiel eines gegebenen Problems findet.
• Eine Sequenz von Schritten, die die Eingabedaten in die gewünschten Resultate überführt.
Beispiel: Sieb des Eratosthenes
Ein Algorithmus zur Ermittlung von Primzahlen.
sieb(n)
notiere aufsteigend alle natürlichen Zahlen
k:=1
do
m:=erste, nicht markierte Zahl größer k
markiere die Vielfachen von m, außer m selbst
k:=m
√
while (k<= n)
alle unmarkierten Zahlen sind Primzahlen
Beispiel: sieb (20)
Start:
2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
für t = 1, k = 1, m = 2:
2 3 x 5
x 7 x 9 x
11 x 13 x 15
x 17 x 19 x
für t = 2, k = 2, m = 3
2 3 x
x 7 x x
11 x 13 x
x 17 x 19
5
x
x
x
für t = 3, k = 3, m = 5
2
2 3 x
x 7 x x
11 x 13 x
x 17 x 19
5
x
x
x
Wir
√ schätzen die Wurzel grob ab:
20 ∼
=5
Beispiel: Binäre Suche, so verfahren wir beispielsweise bei der Telefonbuchsuche:
Gegeben sei eine aufsteigend sortierte Folge von Elementen a1 , a2 , .., an und ein gesuchtes Element x:
bin_suche (a 1, a 2, ..., a n, x)
i := 1
//linker Rand
j := n
//rechter Rand
while (i < j) do
m := ⌈ i+j
2 ⌉ //aufgerundet
if (x > a m)
i := m + 1
else if (x < a m)
j := m − 1
else
return a m
endwhile
return −1
a1
1. Schritt: |{z}
a2
....
am
|{z}
...
m
i
an
|{z}
j
Wenn x > am , dann verschieben wir den linken Rand auf m + 1:
2.Schritt:
a1
a2
....
am
am+1
| {z }
i
1.2
...
an
|{z}
j
Vom Problem zur Lösung am Rechner
Alle Probleme der Infomatik haben etwas gemein. Das interne Verhalten basiert jeweils auf
• der Darstellung: Bestimmung einer systematischen Codierung der Information, so dass diese effizient manipuliert werden kann.
• der Transformation: die sukzessive Modifizierung des Zustands durch das Abarbeiten des Algorithmus, mit dem Zweck, das gewünschte Resultat zu liefern.
1.3
Eigenschaften von Algorithmen
• Diskretheit: ein diskreter Algorithmus arbeitet schrittweise das Problem ab, d.h. er ist aus elementaren Operationen zusammengesetzt.
• Finitheit:
3
– statisch: Die Beschreibung eines Algorithmus besitzt nur eine endliche Länge.
– dynamisch: Ein Algorithmus nimmt während seiner Ausführung nur endlich viel Platz zur
Speicherung von Zwischenresultaten in Anspruch.
• Terminierung: Ein Algorithmus nennt man terminierend, wenn er bei jeder Anwendung nach
endlich vielen Verarbeitungsschritten anhält und ein Resultat liefert.
• Determinismus: Ein Algorithmus nennt man deterministisch, wenn zu jedem Zeitpunkt seiner
Ausführung höchstens eine Möglichkeit der Fortsetzung besteht.
Um für einen Algorithmus die Komplexität analysieren zu können, müssen wir entscheiden, auf welchem
Rechnermodell wir arbeiten wollen.

Pentium II, 266 MHz: 1 MB RAM,...

Programmiersprachen: Haskell, Java, Pascal...
davon müssen wir unabhängig sein!

Compiler
Es muss ein theoretisches, abstraktes Rechnermodell sein. Wir wählen eine Registermaschine, die RAM
(Random Access Machine) [1963].
RAM:
Eine RAM ist ein idealisierter von-Neumann-Rechner und hat folgende Eigenschaften:
1) jede einfache (atomare, elementare) Operation, z.B. +, −, ∗, /, %, =, if, ... benötigt nur eine Zeiteinheit bzw. einen Schritt.
2) Schleifen und Methoden sind keine elementaren Operationen, setzen sich aber aus diesen zusammen
3) Jeder Speicherzugriff dauert genau eine Zeiteinheit. Es gibt unbegrenzten Speicher.
1.4
Komplexität von Algorithmen
Die Komplexität eines Algorithmus beschreibt dessen Kosten (Speicher, Laufzeit. Meistens reicht der
Speicher in der Praxis aus, so dass die Laufzeit das interessante Komplexitätsmaß ist.
Diese kann anhand der Anzahl der elementaren Operationen berechnet werden und hängt von der
Dimension der Eingabe ab: [x1 , x2 , ..., xn ]
{z
}
|
n
Das Sortieren von Listen ist sicherlich abhängig von der Größe der Liste.
1.4.1
Die Landau-Symbolik
Es gibt verschiedene Beschreibungsmöglichkeiten, um die Anzahl der Elementarschritte in Abhängigkeit
von der Größe der Eingabe n anzugeben.
O-Notation: Mit der O-Notation geben wir eine obere Schranke für die Komplexität eines Algorithmus
an. Wir drücken damit aus: dass ein Algorithmus nicht schlechter ist als...“.
”
Mathematisch:
f, g : N → R+
4
f : Marcos binäre Suche, g: Michas grausame Suche
Eine Funktion f (n) hat als obere Schranke g(n), wir schreiben dann
f (n) ∈ O(g(n))
wenn es eine positive Konstante n0 ∈ N und C ∈ R+ gibt, so dass alle Werte von f (n) für n ≥ n0
immer kleiner/gleich c · g(n) sind.
Wir schreiben dafür kurz f (n) ∈ O(g(n)): ∃n0 ∈ N, c ∈ R+ : ∀n ≥ n0 : f (n) ≤ c · g(n)
Abbildung 1: Visuelle Interpretation
Beispiel:
Angenommen wir haben für einen Algorithmus A die folgende Laufzeit ermittelt:
A(n) : 3n4 + 5n3 + 7 log n
Jetzt wollen wir diesen mit B(n) vergleichen, der die Laufzeit von n4 hat.
Mathematisch gesehen sind beide gleich!
Wir behaupten also, dass A(n) ∈ O(B(n))
Beweis:
3n4 + 5n3 + 7 · log n ≤ 3n4 + 5n4 + 7n4
= 15n4
= 15n4
Für n ≥ 1:
15n4 ∈ O(n4 )
n0 = 1, c = 15
Die O-Notation ist nur dann sinnvoll, wenn die zur Abschätzung verwendete Funktion g(n) sinnvoll
ist, also keine überflüssigen Konstanten oder Terme niedrigerer Ordnung enthält.
5
Beispiel:
1) Marco-Programmiersprache
1 Zw
| sum := 0
2n Zw, n Add
| for (i=1 to n)
_____________
|
sum = sum+i
1 + 3n ∈ O(n)
|
2) sum = 0
for (i=1 to n)
for (j =1 to i)
sum = sum +1
Java
|1 Zw
|2n Zw, 2n Add, n if
|____________________
| 1 + 5n ∈ O(n)
|
1
|
+n ·) (
n
·
(
|
2
|
1 )
| )
|_____________________
⇒ O(nˆ2)
| 1 + nˆ2
2
Abbildung 2: Zu Beispiel 2
Wichtige Komplexitätsklassen: (nach unten zunehmende Laufzeit)
Laufzeit
1
logk n
log
√n
n
n
n2
n3
nk
2n
n! ∼ nn
Bezeichung
konstant
polylogarithmisch
logarithmisch
linear
quadratisch
kubisch
polynomial
exponentiell
faktoriell
Optimalität
Ein Algorithmus für ein gegebenes Problem ist dann optimal, wenn seine Komplexität eine untere
Schranke für die Komplexität anderer Algorithmen darstellt, die das Problem ebenfalls lösen.
[ Aoptimal (n), weiter Algorithmen sind: B(n), C(n), D(n)
|{z}
A(n) ∈ O(B(n)) ∧ A(n) ∈ O(C(n)) ∧ A(n) ∈ O(D(n))
Ω-Notation: Mit der Ω-Notation geben wir eine untere Schranke an. Also analog zu O-Notation:
∃n0 ∈ N, c ∈ R+ : ∀n ≥ n0 : f (n) ≥ c · g(n)
wir schreiben dann
f (n) ∈ Ω(g(n))
Θ-Notation: Sollte gelten, dass f (n) ∈ O(g(n)) und g(n) ∈ O(f (n)), dann haben beide die gleiche
Komplexität.
⇒ f (n) ∈ Θ(g(n))
6
Herunterladen