Skript zu Informatik II im Sommersemester 1999

Werbung
Universitat Konstanz
Skript zu Informatik II
im Sommersemester 1999
Karsten Weihe
Konstanzer Schriften in Mathematik und Informatik
Nr. 94, Juli 1999
ISSN 1430{3558
c Fakultat fur Mathematik und Informatik
Universitat Konstanz
Fach D 188, 78457 Konstanz, Germany
Email: [email protected]{konstanz.de
WWW: http://www.informatik.uni{konstanz.de/Schriften
Informatik II
Generalthema:
Algorithmen und Datenstrukturen
Eine beispielorientierte Einfuhrung
in
Algorithmen
und
Datenstrukturen
(mit Java)
Algorithmus: Vorgehensweise zur Erzielung eines
Ergebnisses, ohne dabei nachdenken zu mussen
("Kochrezept\).
;! Auch durch Computer ausfuhrbar.
Datenstruktur: Speicher fur die von
Algorithmen zu bearbeitenden bzw. fur
zusatzlich dafur verwendete Daten.
Wichtigste zu betrachtende Aspekte:
Sommersemester 1999
Universitat Konstanz
Karsten Weihe
Informatik II { Sommersemester 1999
1
Modellbildung,
Korrektheit der Losungen,
Ezienz (Laufzeit),
Speicherplatzverbrauch.
Informatik II { Sommersemester 1999
2
Thema 1: Algorithmische Problemstellung
Fallbeispiel: "passendste\ interpolierende nichtverti-
Oene Frage: Was heit eigentlich "passendst\?
Eingabe: n Mepunkte (x1; y1); : : : ; (xn; yn).
Ausgabe: Steigung der Geraden und ihr Schnittpunkt
mit der y-Achse.
Problem: Bei steilem Anstieg ware eher die horizontale
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
kale Gerade fur Mewerte
3
1. Ansatz fur "passendst\: Summe der
vertikalen Abstande minimal.
Abweichung signikant.
;! Keine gute Modellbildung.
4
2. Ansatz fur "passendst\: Summe der
lotrechten Abstande minimal
Wichtigster Ansatz in der Praxis: Methode der kleinsten Quadrate.
Auch Regressionsanalyse genannt
(;! Statistik).
Summe der Quadrate der vertikalen
Abstande soll minimiert werden.
;! Schon recht genau das, was man will.
Wirklich die "beste\ Denition?
Gibt es uberhaupt die "beste\ Denition!?
Informatik II { Sommersemester 1999
5
Problem:
"Ausreier\ (d.h. ernsthafte Mefehler) haben uber-
proportionalen Einu auf das Ergebnis.
Falls Ausreier durch einseitigen Mefehler erzeugt
werden:
;! Systematische Verfalschung des
Ergebnisses wird noch verstarkt!
Informatik II { Sommersemester 1999
6
Frage:
Warum wird dennoch ausgerechnet diese
Denition gewahlt?
Pragmatische Antwort:
Diese Denition ist mathematisch (und somit algorithmisch) vergleichsweise einfach
handhabbar!
Moglicher Ausweg: "Ausreier\ aus der
Betrachtung herausnehmen.
Beispiel fur eine exakte Denition des
Auswegs:
Finde die Gerade, die "am passendsten\ ist, wenn
nur die 90% Mepunkte, die am nachsten an dieser Gerade liegen, in die Summe der quadrierten
Abstande eingehen.
Informatik II { Sommersemester 1999
7
Informatik II { Sommersemester 1999
8
U ber-/Unterspezikation
Merke:

Uberspezikation:
Exakte Problemdenition ist ein-
Zur automatisierten Bearbeitung eines algorith-
schrankender formuliert als eigentlich beabsichtigt.
Unterspezikation: Exakte Problemdenition enthalt
nicht alle eigentlich beabsichtigten Einschrankungen.
mischen Problems braucht man eine exakte
Problemdenition.
Zu spezizieren sind die zulassigen Eingaben
und das gewunschte Ergebnis, das fur eine
zulassige Eingabe berechnet werden soll.
Alltagsformulierungen\ sind typischerweise
"nicht
exakt genug.
Die exakte Denition zu einer Alltagsformulierung gibt es nicht unbedingt.
;! Freiheitsgrade bei der Umsetzung.
Diese Freiheit kann man nutzen, um zu einer
moglichst gut algorithmisch handhabbaren Problemdenition zu kommen.
Informatik II { Sommersemester 1999
Achtung: U berspezikation kann leicht durch Verwirrung von algorithmischer Problemstellung und algorithmischer Vorgehensweise passieren!
Beispiel: Ausreier bei der Bestimmung der "passendsten\ Megerade eliminieren.
Falle: Die 90% "am besten passenden\ Mepunkte
werden schon in der Problemstellung speziziert.
9
Konkretes Beispiel: Die 10% Mepunkte mit den
Winkeln vom Nullpunkt aus gesehen
"exzentrischsten\
sollen
aus der Berechnung der Summe der Abstandsquadrate herausfallen.
Informatik II { Sommersemester 1999
10
Merke:
U berspezikationen passieren leicht dadurch,
da man dem Algorithmus unbeabsichtigt
"Arbeit abnimmt\.
Dadurch ist der Algorithmus in seinen
Moglichkeiten unnotig (und vielleicht entscheidend!) eingeschrankt.
Also: Algorithmische Problemstellung und algorithmische Vorgehensweise beim Nachdenken konsequent auseinanderhalten.
Logische Inkorrektheit: Die 10% Mepunkte sollten
nicht a priori gegeben sein, sondern sich eigentlich erst
aus dem Ergebnis des Algorithmus ergeben.
Informatik II { Sommersemester 1999
11
Informatik II { Sommersemester 1999
12
Noch einmal zuruck zum Thema algorithmisch gut
handhabbare Problemstellungen\ "
Extremfall: algorithmenorientierte statt problemorien-
tierte Spezikation der algorithmischen Problemstellung.
Newton{Verfahren:
xn+1 := xn ; ff0((xxn))
(n 0)
n
Beispiel:
Eingabe: Funktion f : R ;! R , Ableitungsfunktion
f 0 sowie ein x0 2 R .
Ausgabe: Nullstelle von f .
Zulassige Eingaben: f konvex und streng monoton
zwischen x0 und Nullstelle.
;! Newton{Verfahren zur Nullstellenberechnung liefert beweisbar eine
korrekte Losung.
x3 x 2
x1
x0
Frage: Wozu sind solche algorithmen- statt problemorientierte Spezikationen gut?
Informatik II { Sommersemester 1999
13
Wozu algorithmenorientierte Spezikationen?
Informatik II { Sommersemester 1999
14
Veranschaulichung Quadratwurzelberechnung
Antwort: Als "gemeinsamer Nenner\ fur diverse Spe-
per Newton{Verfahren:
zialfalle, die durch denselben schnellen, aber nicht
allgemein anwendbaren Algorithmus gelost werden
konnen.
Beispiel fur solche Spezialfalle:
Quadratwurzelberechnung.
Zulassige Eingabe: y 2 R , y 0.
Gewunschte Ausgabe: py.
Losungsidee: Finde nichtnegative Nullstelle der
Funktion f : R ;! R mit f (x) = x2 ; y.
Startlosung: x0 := maxf1; yg.
;! x0 py garantiert.
Informatik II { Sommersemester 1999
- y
15
Informatik II { Sommersemester 1999
-y
y
max{1,y }
16
Variationen vs. Spezialfalle von algorithmischen
Problemstellungen
Zuruck zum Thema Megerade ...
Beispiele fur Variationen:
Die Gerade soll nicht durch Steigung und Schnitt
Beispiele fur Spezialfalle:
Alle Mepunkte haben ganzzahlige Werte.
Es gibt niemals mehr als 100 Mepunkte.
Keine zwei Mepunkte haben dieselbe
x{Koordinate.
Informatik II { Sommersemester 1999
17
Beliebter Denkfehler: Manche Variation sieht wie
Spezialfall aus
;! scheint einfacher (ezienter) losbar zu sein.
Beispiel: Gerade soll ganzzahlige Steigung
haben.
Kein Spezialfall, sondern nur\ eine Variation (und
tatsachlich auch wesentlich"aufwendiger zu losen!).
Informatik II { Sommersemester 1999
19
punkt mit der y-Achse, sondern durch zwei Punkte
auf der Geraden ausgegeben werden.
Die Gerade mu durch den Nullpunkt gehen.
Die Steigung soll ganzzahlig sein.
Vertikale Geraden sind zugelassen.
Allgemeinere Kurven anstelle von Geraden.
Dreidimensionale Variante des Problems.
Informatik II { Sommersemester 1999
18
Merke:
Ein Spezialfall liegt vor, wenn die zulassigen
Eingaben fur den Algorithmus eingeschrankt
werden.
Alles andere sind Variationen.
Insbesondere: Einschrankungen bei der Ausgabe konstituieren keinen Spezialfall, sondern eine Variation!
Nur wenn A ein wirklicher Spezialfall von B
ist, kann man logisch folgern, da A mindestens genauso ezient losbar ist wie B . Ist
A nur eine Variation von B , lat sich ohne
weiteres Wissen uber A und B gar nichts
folgern.
Informatik II { Sommersemester 1999
20
Fallbeispiel aus der Praxis:
Vereinfachtes Beispiel fur Ablaufplane:
Auftragsplanung im Stahlwerk
(stark vereinfacht!)
Jeder Kundenauftrag speziziert
Metallschmelze
{ spatesten Liefertermin,
{ Art des Produkts
Warmwalzen
Abkühlen
(z.B. Draht, Blech, Trager...),
{ Abmessungen
(z.B. Drahtdurchmesser/-lange,
Blechstarke/-breite/-lange),
{ Material und Legierung,
{ Sonderbehandlungen
(z.B. Farbung, Beizung...).
Kundenauftrag wird in Ablaufplan
umgesetzt.
Ablaufplan: Folge von Operationen auf
verschiedenen Maschinen, um das Endprodukt aus einer Schmelze herzustellen.
Informatik II { Sommersemester 1999
Transport zum Kaltwalzwerk
Kaltwalzen
Transport
Drahtziehen
Transport
Färben
Lagerung zum Trocknen
Transport ins Endlager
Endprodukt
21
Algorithmisches Ziel: Zeitliche Einplanung
22
Was soll passieren, wenn der Algorithmus keine
aller Operationen, so da alle Nebenbedingungen erfullt sind:
Losung ndet?
Jede Operation hat ihre spezische Bearbeitungs-
zeit.
Jede Maschine bearbeitet zu jedem Zeitpunkt maximal eine Operation.

Minimale und maximale Ubergangszeiten
zwischen
zwei aufeinanderfolgenden Operationen eines Auftragsplans mussen eingehalten werden.
Beobachtungen:
Die Nebenbedingungen konnen das
Problem unlosbar machen.
Falls uberhaupt losbar, kann es mehrere
Losungen geben.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
23
Mogliche, sinnvolle Antworten:
Er soll eine "moglichst wenig inkorrekte\ Losung
liefern.
;! Einige der "harten\ Nebenbedingungen
mussen zu "weichen\ Zielsetzungen werden (z.B. Einhaltung aller Liefertermine).
Er soll eine Diagnostik liefern, z.B.
{ welche Maschinen wann jeweils der "Flaschenhals\ sind,
{ welche Liefertermine unmoglich einzuhalten sind.
;! Hilfreiche Information, damit Druck
durch geeignete betriebliche Manahmen abgefangen werden kann (z.B.
zusatzliche Arbeitsschichten).
Zur Diagnostik konnen auch konkrete Vorschlage
fur solche betrieblichen Manahmen gehoren.
Informatik II { Sommersemester 1999
24
Allgemein beliebte Falle: Vergessen von
Merke:
"simplen\ Randfallen
Beispiel: Maschine im Stahlwerk kann uber den gesamten betrachteten Zeitraum hinweg auer Betrieb
sein.
Ein algorithmisches Problem kann mehrere
Losungen haben.
Oder auch gar keine.
Exakte Denition der algorithmischen Problemstellung mu ggf. auch das Ergebnis "keine Losung\ zulassen.
Insbesondere bedeutet Ergebnis "keine
Losung\ nicht unbedingt Fehlverhalten
des
Algorithmus.
Typische Variationen zur Behandlung dieser
Aspekte sind:
{ Forderung nach mehreren alternativen
Losungen zum Auswahlen,
{ diagnostische Zusatzausgaben,
{ Eingrenzung der Losungsmenge anstelle
von konkreten Losungen.
Informatik II { Sommersemester 1999
Beispiel fur Konsequenzen: Algorithmus darf nir-
gendwo einfach durch die Gesamtbetriebszeit einer
Maschine dividieren!
Problem konnte im Prinzip dadurch gelost werden,
da eine solche Maschine aus der Betrachtung genommen wird.
Aber: Konnte potentiell zu umstandlich sein.
Also: Damit keine Zweifel aufkommen, sollte die Spezikation der algorithmischen Problemstellung ausdrucklich den Fall Gesamtbetriebszeit 0 einschlieen.
25
26
Thema 2: Generische Problemstellungen
Merke:
Wieder zuruck zum Beispiel \`interpolierende Megerade\...
Bei der genauen Spezikation einer algorith-
mischen Problemstellung mu immer besonderes Augenmerk auf die "Randfalle\ gelegt
werden.
Da ein Randfall "prinzipiell vermeidbar\
ware, bedeutet nicht unbedingt, da er in der
Praxis auch wirklich unter allen Umstanden
vermieden wird.
Oft ist es namlich einfach zu umstandlich,
den Randfall vorab abzufangen.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
Beobachtung:
Der genaue Zahlentyp spielt fur die algorithmische
Problemstellung keine Rolle.
Allgemein:
Jeder Zahlentyp, auf dem der Abstand zwischen Punkten (x1; y1) und (x2; y2) deniert ist, kann in die
Problemstellung eingesetzt werden.
27
Naturliche Zahlen
Ganze Zahlen
Rationale Zahlen
Reelle Zahlen
...
Informatik II { Sommersemester 1999
28
Fortsetzung Generizitat
Intuition hinter "Manhattan{Distanz\:
Weitere Beobachtung: Verschiedene Abstandsde-
nitionen (Metriken) konnen auf demselben Zahlentyp
deniert sein.
Beispiele:
Normaler (Euklidischer) Abstand: Lange der Verbindungsstrecke
p
(x1 ; x2)2 + (y1 ; y2)2
(Mathematischer Begri: 2{Metrik)
Manhattan-Distanz:
jx1 ; x2j + jy1 ; y2j
(Fahrdistanz in Manhattan{artig angelegten Stadten; mathematisch: 1{Metrik)
Informatik II { Sommersemester 1999
29
"Esoterische\ Beobachtung:
Informatik II { Sommersemester 1999
30
Standardbeispiel fur Generizitat: Sortieren
Man braucht sich eigentlich gar nicht auf Zahlentypen zu beschranken.
Jede Menge mit einem Abstandsbegri ist moglich.
Beispiel: Strings der Lange m mit Hamming-Abstand
Gegeben: Sequenz (a1; : : : ; an) von zu
sortierenden Werten.
Gesucht: Permutation der Sequenz, so da gilt:
(a1) (a2) (an)
Einfaches Zahlenbeispiel:
Abstand zweier Strings
=
17 21 41 67 12 41 15 23 88 9
Anzahl der ungleichen Zeichen
9 12 15 17 21 23 41 41 67 88
Informatik II { Sommersemester 1999
31
Informatik II { Sommersemester 1999
32
Generische Freiheitsgrade:
Datentyp fur die Werte a1; : : : ; an,
Konkretes Beispiel: Datensatze fur immatrikulierte
Denition von "\,
Datentyp fur die Sequenz (z.B. Array).
Vorgri: Fur die meisten in dieser Vorlesung behan-
delten Sortieralgorithmen ist die Festlegung dieser drei
Freiheitsgrade unerheblich!
Studierende.
Enthalten als Daten z.B. Vorname, Nachname,
Fachrichtung, Matrikelnummer.
Sinnvolle Denitionen von "\:
{ "Telefonbuchordnung\ auf den Namen
(Fachbegri: lexikographisch)
;! Reihenfolge nicht eindeutig.
{ Nach Matrikelnummern
;! Reihenfolge eindeutig.
{ Nach Geburtsdaten
;! Reihenfolge wieder nicht eindeutig.
;! Spater mehr zum Thema Sortieren.
Informatik II { Sommersemester 1999
33
Mathematische Exkursion: abstrakte
Informatik II { Sommersemester 1999
34
Technische Exkursion: potentielles Zusammenfallen
Datentypen
von Ein- und Ausgabe
Beispiel: wieder Immatrikulationsdaten
Datentyp
= Menge von moglichen Werten
+ Operationen
+ axiomatische Regeln fur die
Operationen
StudentIn[]
sort (StudentIn[] A)
Erlauterung:
Beispiel: Mathematische Gruppe.
Eingabe: Parameter A.
Ausgabe: Ruckgabewert von sort.
tion.
Rationale und reelle Zahlen (ohne 0) jeweils mit
Multiplikation.
Alternative:
Generischer Algorithmus
Algorithmus auf abstrakten Datentypen.
A
Ganze, rationale und reelle Zahlen jeweils mit Addi-
Informatik II { Sommersemester 1999
{ ... }
void
sort (StudentIn[] A)
{ ... }
ist nun Ein- und Ausgabe
;! eine Kopieraktion eingespart.
35
Informatik II { Sommersemester 1999
36
Weiteres Beispiel fur generische algorithmische Pro-
Schnellste Fahrverbindung mit dem Zug:
blemstellungen: Optimale Verbindungen in Netzwerken
Generische Problemstellung
Kürzeste
Autoverbindung
Schnellste
Bahnverbindung
Billigste
Flugverbindung
Preis\ einer Verbindung von A nach B (vereinfacht):
"Summe
der Einzelpreise fur die elementaren Fahrten.
;! Problemstellung benotigt zwei Operationen auf dem Datentyp fur Preise: Addition und Minimumsbildung.
Informatik II { Sommersemester 1999
37
Sinnvolles Beispiel fur generisches Oenhalten des
Zahlentyps:
"Preis\ einer elementaren Fahrverbindung: Paar
(a; b) von Zahlen.
Addition: (a; b) + (c; d) = (a + c; b + d).
Minimum von (a; b) und (c; d):
= (a; b) falls a < c,
= (a; b) falls a = c und b < d,
= (c; d) sonst.
Sinn des Ganzen:
38
Zunachst obskur erscheinende generische
Variation: Ersetze
Addition durch Multiplikation und
Minimum durch Maximum.
DM
ÖS
SFr
US $
;! "Kurzeste\ Verbindung von Wahrung A
nach Wahrung B mit Umtauschkurs als
"Preis\ ergibt gunstigste Umtauschkette.
;! Auch dieses Problem ist im Prinzip mit
demselben Algorithmus fur "kurzeste Wege\ losbar!
1. Zahl: Fahrpreis.
2. Zahl: Fahrzeit.
;! Optimaler Pfad mit diesem "Zahlentyp\
und dieser Denition von Addition und
Minimumsbildung ist die schnellste Verbindung unter allen billigsten!
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
39
Informatik II { Sommersemester 1999
40
Unerwartetes Beispiel fur
kurzeste Wege: Blockformatierung von Texten in Textverarbeitungssystemen
Knotenpunkte: alle Silben
sowie "{ Ende {\.
Verbindung: Von jeder Silbe
zu jeder nachfolgenden.
"Preis\ einer Verbindung:
der zu"Haolichkeitsgrad\
geh
rigen Zeile.
Formatierung Pfad von erster Silbe
bis "{ Ende {\.
Un
er
war
te
tes
Bei
spiel
für
kür
ze
ste
We
ge:
Block
for
ma
tierung
von
Tex
ten
in
Text
ver
ar
bei
tungs
sy
ste
men
-Ende -
Informatik II { Sommersemester 1999
Merke:
In vielen Problemstellungen kann der zu-
grundeliegende Datentyp in gewissen Grenzen oengelassen werden, und Losungsalgorithmen werden mit den sich ergebenden Variationsmoglichkeiten trotzdem fertig.
Fur den Datentyp mussen nur gewisse Operationen deniert sein, die fur die Problemstellung wesentlich sind.
Weiterer Freiheitsgrad: Diese Operationen
konnen unterschiedlich deniert sein (auch
in ungewohnlicher, unerwarteter Weise).
41
Technische Exkursion: Wie kann man die Implemen-
tation eines Algorithmus in Java so generisch wie den
Algorithmus selbst halten?
Informatik II { Sommersemester 1999
42
Ergebnis:
void sort (Object[] A, Comparator cmp)
{
...
Idee:
Konkreten Datentyp durch den "allumfassenden\
Typ comp.lang.Object ersetzen.
Operation "\ durch einen weiteren Parameter von
einem neuen Typ Comparator\
reprasentieren. "
// Beispielhafte Anwendung von "isLessThan":
if ( cmp.isLessThan(A[i],A[j]) )
...
}
"Comparator\ hat Methode
boolean isLessThan (Object obj1, Object obj2)
zum Vergleich zweier Werte des Datentyps.
Informatik II { Sommersemester 1999
43
Informatik II { Sommersemester 1999
44
Implementation von "isLessThan\
Beispiel: fur Datentyp int und gewohnliche Ordnungsrelation auf ganzen Zahlen.
Kurzer Ausblick:
Java{Erweiterung GJ (Generic Java)
Implementation von isLessThan:
boolean isLessThan (Integer int1, Integer int2)
{
int
i1
= int1.intValue();
int
i2
= int2.intValue();
return i1 < i2;
}
boolean isLessThan (Object obj1, Object obj2)
{
Integer int1 = (Integer)obj1;
Integer int2 = (Integer)obj2;
int
i1
= int1.intValue();
int
i2
= int2.intValue();
return i1 < i2;
}
Nun sort selbst:
<T> void sort (T[] A, Comparator<T> cmp)
{
...
Achtung:
void sort (Object[] A, Comparator cmp)
Paar (A,cmp) ist nur dann eine zulassige Eingabe, wenn
alle Komponenten von A den Datentyp haben, der von
cmp.isLessThan erwartet wird.
Informatik II { Sommersemester 1999
45
<T> void sort (T[] A, Comparator<T> cmp)
sort
Bemerkung: Generische Typen und Prozeduren gibt
es in verschiedenen Programmiersprachen (z.B. Ada,
C++, Eiel, Haskell, ML), aber eben (noch?) nicht in
Java.
Informatik II { Sommersemester 1999
}
Informatik II { Sommersemester 1999
46
Merke:
Erlauterung: Datentyp ist jetzt explizit, aber immer
noch generisch (d.h. durch einen "Platzhalter\, im
Beispiel durch "T\) in der Implementation von
formuliert.
;! Beim U bersetzen wird schon automatisch
getestet, ob A und cmp zusammenpassen.
;! Die "Zeitbombe\ ist "entscharft\.
// Beispielhafte Anwendung von "isLessThan":
if ( cmp.isLessThan(A[i],A[j]) )
...
47
Im Prinzip lassen sich generische Algorithmen
in Java auch entsprechend generisch implementieren.
Allerdings mu beim Programmieren "per
Hand\ darauf geachtet werden, da die Datentypen der Eingabeparameter zusammenpassen.
In groeren Programmen kann man leicht die
U bersicht verlieren und Fehler einbauen, die
dann oftmals muhselig und langwierig durch
Testlaufe zuruckverfolgt werden mussen.
In anderen Programmiersprachen gibt es sogenannte generische Sprachkonstrukte (auch
Templates genannt), die dafur sorgen, da
der Compiler jeden solchen Fehler anzeigt.
Informatik II { Sommersemester 1999
48
Thema 3: Korrektheit von Algorithmen
Wiederholung aus Thema 1: Spezikation einer algorithmischen Problemstellung gibt die zulassigen Eingaben an und beschreibt das gewunschte Ergebnis fur
eine zulassige Eingabe in allgemeiner Form.
Denition: Ein Algorithmus heit korrekt bzgl. ei-
ner (exakt spezizierten!) algorithmischen Problemstellung, wenn er bei einer zulassigen Eingabe
nur wohldenierte Schritte macht,
terminiert (d.h. in keine Endlosschleife lauft) sowie
bei Termination das laut Spezikation
gewunschte Ergebnis liefert.
Informatik II { Sommersemester 1999
49
Achtung:
Wohldenierte Schritte...
Beispiele fur nicht wohldenierte Schritte:
Division durch 0,
Operationen mit arithmetischem U berlauf,
Zugri auf Arraykomponente auerhalb des Indexbereichs,
Zugri auf nichtinitialisierte Variable.
Beachte: Nicht wohldenierte Schritte fuhren zu undeniertem Verhalten des Programms im weiteren:
Programmabsturz,
Endlosschleife,
Rechnerstillstand,
Termination mit inkorrekten Ergebnissen
Termination mit korrekten Ergebnissen
...
Informatik II { Sommersemester 1999
50
Merke:
Arithmetischer U berlauf kann manchmal
uberraschend schnell passieren!
Beispiel: Binomialkoezient berechnen mittels Fakultat m! = 1 2 3 (m ; 1) m.
n
n!
k := k! (n ; k)!
Korrektheit eines Algorithmus ist nicht abso-
lut, sondern immer nur relativ zur zugrundeliegenden Spezikation der algorithmischen
Problemstellung zu verstehen.
Zur Korrektheit gehoren als Grundvoraussetzungen Wohldeniertheit und Termination.
int binomcoeff (int n, int k)
{
return faculty(n) / (faculty(k) * faculty(n-k));
}
Problem: Java{Datentyp int kann nur Zahlen bis
231 ; 1 = 2:147:483:647 darstellen.
;! Arithmetischer U berlauf schon fur n 13.
Informatik II { Sommersemester 1999
51
Informatik II { Sommersemester 1999
52
Korrektheit unter numerischer Unsicherheit
Beispiel: Quadratwurzelberechnung
Problem: Die meisten Quadratwurzeln sind irrationale
Zahlen.
;! Problem ist prinzipiell nicht exakt losbar.
Wichtigste Beispiele fur Abstandsfunktionen in der
Praxis:
Absoluter Fehler: x x0, wenn jx ; x0j " ist.
Relativer Fehler: x x0, wenn gilt:
jx ; x0j " maxfx; x0g.
Grundidee:
Approximative Losung x fur die eigentliche Losung
x0 wird als korrekt gewertet, wenn x x0.
x x0 ist auf Basis einer Abstandsfunktion und
eines festen Schwellwerts " > 0 deniert: x x0,
Unterschied: Aussagekraft des relativen Fehlers hangt
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
wenn der Abstand zwischen x und x0 den Schwellwert " nicht uberschreitet.
53
nicht von der Groenordnung der (willkurlich gewahlten) Konstante " im Verhaltnis zu x und x0 ab.
54
Beispiel: Konkrete Idee fur Quadratwurzelberechnung
mittels Newton
Merke:
Es gibt algorithmische Probleme, die prinzipi-
ell nicht exakt losbar sind.
Ursache: Diskrepanz zwischen mathematischen Zahlen mit unendlicher Genauigkeit und
Maschinenzahlen mit endlicher Stellenzahl.
In einem solchen Fall mu die gesuchte
Losung approximiert werden.
Besonders bewahrt in der Praxis: relativer
Fehler als Ma fur die Gute einer approximativen Losung.
Informatik II { Sommersemester 1999
- y
-y
y
max{1,y }
Sei z 2 (0; py ] beliebig
;! f 0(x) = 2x 2z = f 0(z) fur x py
;! f (x) g(x) := 2z (x ; py) fur x py.
55
Informatik II { Sommersemester 1999
56
Veranschaulichung:
Merke:
Da der Zielwert nicht bekannt ist, mu der
f
Test, ob die Fehlerschranke schon unterschritten wurde, haug indirekt mittels Berechnung
anderer Werte arbeiten.
Es gibt keine allgemeine Methode, geeignete
Tests fur beliebige Algorithmen zu konstruieren, sondern wie bei Algorithmen selbst ist
jedesmal von Neuem Kreativitat gefragt.
g
z
y
x
;! Sobald f (x) " 2z gilt, ist x ; py "
erreicht.
Genaueres zum Thema Behandlung numerischer Fehler: Veranstaltungen zur Numerischen Mathematik.
Informatik II { Sommersemester 1999
57
Fallbeispiel aus der Praxis: Rekonstruktion fehler-
hafter Nachbarschaften zwischen Flachenelementen im
CAD
Informatik II { Sommersemester 1999
58
Fehler in den Daten: Fehlerhafte Spalte
zwischen Flachenelementen
CAD{Modell einer Pumpe:
Informatik II { Sommersemester 1999
59
Informatik II { Sommersemester 1999
60
Extrembeispiel fur Datenfehler (gefunden im Innern
der Pumpe):
Algorithmische Problemstellung: Fehlerhafte Spalte
von beabsichtigten O nungen unterscheiden.
Einsicht:
Es kommen zwar sehr viele fehlerhafte Spalte vor,
aber die meisten sind eher schmal (uberwiegend auf
den Bildern nicht einmal sichtbar).
O nungen hingegen sind eher breit.
;! Idee:
Abstandsfunktion fur Paare von Flachenelementen
denieren.
Schwellwert " > 0 unterscheidet fehlerhafte Spal-
te zwischen Flachenelementen von beabsichtigten
O nungen.
111
000
111
111 000
000
111
000
111
000
111 000
000
111
Informatik II { Sommersemester 1999
61
Beispiele fur sinnvolle Abstandsfunktionen zwischen
Flachenelementen:
Minimaler Abstand von irgendeinem Punkt auf einem Element zu irgendeinem Punkt auf dem anderen Element.
Durchschnittlicher Abstand von einander "gegenuberliegenden\ Randpunkten.
Flache in der Lucke zwischen den einander gegenuberliegenden Randsegmenten.
;! Alles Mae fur den absoluten Fehler.
Informatik II { Sommersemester 1999
62
Bonbon\ zum Abschlu: Visualisierung des Ergeb"nisses
durch Einfarben von Randern gema Anzahl der
anliegenden Flachenelemente
Relativer Fehler: " multipliziert mit einem Ma fur
die Groe der Flachenelemente (z.B. Flacheninhalt,
Durchmesser, Umfang).
Unterschied: Relativer Fehler ist von der
Skalierung des Modells unabhangig.
Informatik II { Sommersemester 1999
63
Informatik II { Sommersemester 1999
64
Erinnerung: Ein Algorithmus heit korrekt ... wenn er
bei einer zulassigen Eingabe ...
Beachte: Es wird nichts uber das Verhalten des Algorithmus bei nichtzulassigen Eingaben ausgesagt!
Konkret: Algorithmus ist auch dann korrekt, wenn er
Merke:
Informell bedeuten absoluter bzw. relativer
Fehler: Die Diskrepanz zwischen Ziel und Ergebnis wird ohne bzw. mit Berucksichtigung
der Groe der auftretenden Objekte berechnet.
Falls diese Objekte in beliebiger Skalierung
auftreten konnen, ist der absolute Fehler kein
adaquater Mastab, nur der relative.
Informatik II { Sommersemester 1999
bei nichtzulassigen Eingaben absturzt, in Endlosschleife
lauft oder sonstigen Blodsinn macht!
Prinzip Design{by{Contract:
Spezikation ist "Vertrag\ zwischen dem Algorithmus und seinem "Kunden\.
Kunde erfullt den Vertrag, wenn er nur zulassige
Eingaben macht.
Dann (und nur dann!) ist der Algorithmus "vertraglich\ verpichtet, korrekt zu laufen und die korrekte
Ausgabe zu liefern.
65
Einfaches Beispiel Design{by{Contract:
Mogliche Eingaben: ganze Zahlen n
66
Warum Design{by{Contract?
Konkret: Warum nicht einfach im Algorithmus fur n!
die Bedingung n > 0 abtesten und im Fall n 0 eine
(z.B. Java{Datentyp int).
Zulassige Eingaben: n > 0.
Gewunschte Ausgabe: n!, d.h.
1 2 3 (n ; 1) n.
Fehlermeldung liefern?
Mogliche Formen fur Fehlermeldung:
Gefahr: "Kunde\ kann leicht seinen Teil des Vertrags
vergessen bzw. in komplexeren Fallen unsachgema
oder nur unzureichend erfullen.
;! Potentiell undeniertes Programmverhal-
"Unmoglicher\ Wert anstelle von n! (z.B. ;1).
int faculty (int n)
// Liefert n!, falls n>0, sonst -1
Zusatzlicher Boolescher Parameter, der angibt, ob
ten sowohl im Algorithmus als auch (falls
es uberhaupt soweit kommt) nach Termination des Algorithmus im weiteren Programmverlauf.
Ergebnis korrekt ist:
int faculty (int n, Boolean resultIsCorrect)
// Ergebnis ist n!, falls
Oene Frage: Wenn Design{by{Contract so gefahrlich ist | warum dann uberhaupt?
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
67
// resultIsCorrect.valueOf() == true
Informatik II { Sommersemester 1999
68
Also: Warum nun Design{by{Contract?
1. Antwort: Wenn Kunde kein Problem hat, den
Vertrag zu erfullen, kostet das zusatzliche Abtesten
unnotig Laufzeit.
Beispiel fur signikanten Ezienzverlust:
Eingaben: Liste von Personendaten fur Studierende
sowie eine Zahl n.
Zulassige Eingaben: Alle Matrikelnummern mussen
verschieden voneinander sein.
Gewunschte Ausgabe: Der/die Studierende mit Matrikelnummer n (bzw. Meldung "existiert nicht\).
Vorgri auf spateren Abschnitt der Vorlesung: Suchen einer Matrikelnummer geht um Groenordnungen
schneller als der Test, da alle Matrikelnummern verschieden sind.
;! Design{by{Contract reduziert hier die
nur schwierig oder sogar unmoglich zu testen.
Beispiel: wieder algorithmenorientierte Problemstellung fur das Newton{Verfahren.
Zur Erinnerung:
x3 x 2
x1
x0
Bedingungen an die Funktion f : Monotonie und Konvexitat.
Laufzeit um Groenordnungen.
Informatik II { Sommersemester 1999
Fortsetzung warum Design{by{Contract
2. Antwort: Zulassigkeit der Eingabe ist manchmal
69
Technische Exkursion: Wie eine Funktion wie f an
einen Algorithmus wie "Newton\ ubergeben?
Idee: ahnlich wie bei der generischen Implementation
von sort zuvor.
Interface Function denieren:
interface Function
{
double value (double x);
}
Informatik II { Sommersemester 1999
70
Nun der Newton{Algorithmus selbst:
double findZeroUsingNewton
(Function f, Function fDerived,
NumericErrorChecker checker,
double start)
{
Bei der Gelegenheit ... auch den Test auf "Nullstelle
double x = start;
while ( ! checker.closeToSomeZero(f,x) )
x = x - f.value(x) / fDerived.value(x);
}
genau genug erreicht\ durch zusatzlichen Parameter
exibel halten:
interface NumericErrorChecker
{
boolean closeToSomeZero (Function f, double x);
}
Erlauterung: Ruckgabe ist true genau dann, wenn
x Nullstelle.
Informatik II { Sommersemester 1999
71
Informatik II { Sommersemester 1999
72
Zuruck zum Ausgangspunkt: 2. Antwort auf "warum
Fortsetzung warum Design{by{Contract
Erinnerung: Behauptung ist, da Zulassigkeit der Eingabe manchmal nur schwierig oder sogar unmoglich zu
testen ist.
3. Antwort: Die Menge der zulassigen Eingaben ist
Design{by{Contract?\
Konkretes Problem: Wie sollen Monotonie und Kon-
vexitat eines Function{Objekts eigentlich gepruft werden?
Wenn Funktion nur Methode value bietet, gibt es
nicht unbedingt formal fabar.
Wieder Beispiel Newton{Verfahren:
Verfahren funktioniert auch auf Funktionen f , die
nicht die oben formulierten strengen Bedingungen
an Monotonie und Konvexitat erfullen.
nur eine Moglichkeit: die Funktionswerte fur alle x
berechnen.
;! Unrealistisch.
"Strohhalm\: Weitere Methoden fur Function,
die den Test auf Monotonie und Konvexitat unterstutzen.
Leider: keine allgemein anwendbare Idee fur solche
Methoden in Sicht.
Problem: "Grenzlinie\ zwischen geeigneten und ungeeigneten Funktionen ist weitgehend unbekannt.
;! Jeder Test auf Zulassigkeit der Eingabe
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
73
weist entweder geeignete Funktionen ab
oder lat ungeeignete Funktionen durch.
74
Thema 4: Korrekte Algorithmen
Einfuhrendes Beispiel: Bisektionsverfahren zur Be-
Merke:
rechnung einer Nullstelle.
Zulassige Eingabe: Stetige Funktion f : R ;! R ,
reelle Zahlen a < b, so da entweder f (a) < 0 und
f (b) > 0 oder f (a) > 0 und f (b) < 0 ist.
Gewunschte Ausgabe: Approximation des x{Wertes
einer Nullstelle von f im Intervall [a; b].
Die Einschrankung der Korrektheit auf
zulassige Eingaben (Design{by{Contract) ist
potentiell gefahrlich.
Aus verschiedenen Grunden mu Design{by{
Contract dennoch haug angewandt werden:
{ algorithmische Ezienz,
{ Test auf Zulassigkeit der Eingabe potentiell
unmoglich,
{ potentiell uberhaupt keine befriedigende
Spezikation zum Abtesten der Zulassigkeit von Eingaben verfugbar.
f(a)
b
a
f(b)
Informatik II { Sommersemester 1999
75
Informatik II { Sommersemester 1999
76
Vorarbeit zur Vereinfachung:
Funktion differentSign testet ab, ob zwei reelle
Zahlen x und y unterschiedliches Vorzeichen haben.
Algorithmischer Ansatz
(der Einfachheit halber nur mit absolutem Fehler):
double
left_end = a;
double right_end = b;
while ( left_end + 2*epsilon < right_end )
{
double middle = ( left_end + right_end ) / 2;
if ( differentSign ( f(left_end), f(middle) ) )
right_end = middle;
else
left_end = middle;
}
return ( left_end + right_end ) / 2;
boolean differentSign ( double x, double y )
{
if ( x > 0 && y < 0 )
return true;
if ( x < 0 && y > 0 )
return true;
return false;
}
Informatik II { Sommersemester 1999
77
Informatik II { Sommersemester 1999
Veranschaulichung:
a
1
3 42
78
...
while ( left_end + 2*epsilon < right_end )
{
double middle = ( left_end + right_end ) / 2;
if ( differentSign ( f(left_end), f(middle) ) )
right_end = middle;
else
left_end = middle;
}
...
b
Schleifeninvarianten: Am Anfang und Ende jedes
Schleifendurchlaufs gilt
left_end < right_end
differentSign(f(left_end),f(right_end)) == true
Konsequenz daraus (zusammen mit der Stetigkeit von
f ): Am Anfang und Ende jedes Schleifendurchlaufs
liegt mindestens eine Nullstelle von f im momentanen
Intervall [left
Informatik II { Sommersemester 1999
79
end,right end].
Informatik II { Sommersemester 1999
80
Schleifenvariante: Nach k Durchlaufen der
Merke:
Schleife gilt (Rundungsfehler vernachlassigt):
right end
; left
end
Ein nichttrivialer Algorithmus besteht "im we-
= b 2;k a
Konsequenz: Programm terminiert, sobald
b;a 2"
2k
;! Programm terminiert nach
b ; a log2 2 "
Durchlaufen durch die Schleife.
Informatik II { Sommersemester 1999
81
Wichtige Einsicht: Korrektheit des Algorithmus ist
nun beweisbar.
Erinnerung: Ein Algorithmus heit korrekt bzgl. einer
Spezikation einer algorithmischen Problemstellung,
wenn er bei einer nach dieser Spezikation zulassigen
Eingabe
nur wohldenierte Schritte macht,
terminiert und
ein gema Spezikation korrektes Ergebnis liefert.
sentlichen\ aus einer oder mehreren Schleifen (die auch ineinandergeschachtelt sein
konnen).
Ausnahme: rekursive Algorithmen (spater).
Eine Schleifeninvariante ist eine Aussage uber
die Werte von Variablen, die in jedem Durchlauf gultig ist.
Eine Schleifenvariante ist eine Aussage uber
die A nderung von Variablenwerten von Durchlauf zu Durchlauf.
Zur Formulierung einer Invariante oder Variante gehort unbedingt dazu, an welcher Stelle
der Schleife genau sie gultig sein soll (meist
Anfang/Ende).
Informatik II { Sommersemester 1999
82
Nun konkreter Korrektheitsbeweis fur das
Bisektionsverfahren:
Oensichtlich keine undenierten Schritte.
Erinnerung: Schleife terminiert nach maximal
dlog2( b2;"a )e Durchlaufen.
;! Algorithmus als Ganzes terminiert.
Schleifeninvariante
;! Auch bei Termination liegt immer noch eine Nullstelle zwischen
left end und right end.
;! Ruckgabewert der Bisektionsfunktion
ist hochstens " von irgendeiner Nullstelle entfernt.
;! Ruckgabewert ist korrekt gema absolutem Fehlerma.
Informatik II { Sommersemester 1999
83
Informatik II { Sommersemester 1999
84
Weiteres Beispiel: Fibonacci{Zahlen
fib(1) = fib(2) = 1,
fib(n) = fib(n ; 1) + fib(n ; 2) fur n > 2.
Notation: xi, yi und zi seien die Werte von x, y
und z unmittelbar nach der Addition "z = x + y\ im
Durchlauf Nr. i durch die Schleife.
Drei Schleifeninvarianten:
xi = fib(i ; 2),
yi = fib(i ; 1),
zi = fib(i).
;! Es gilt z = fib(n) nach dem allerletzten
;! 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
Algorithmus in Java:
int fibonacci ( int n )
// Voraussetzung nach
// "Design-by-Contract": n > 0.
{
if ( n <= 2 )
return 1;
int x;
int y = 1;
int z = 1;
for ( int i = 3; i <= n; i++ )
{
x = y;
y = z;
z = x + y;
}
return z;
}
Informatik II { Sommersemester 1999
Durchlauf.
;! Ruckgabewert von bonacci ist oensichtlich korrekt.
Beachte: Sowohl die Scheifenvarianten selbst als auch
die Korrektheit des Algorithmus auf Basis der Schleifeninvarianten lassen sich wesentlich einfacher durchschauen und nachvollziehen als der Algorithmus als
Ganzes.
Psychologischer Hintergrund: Komplexe, nichtlineare Ablaufe sind in eine Folge von Schnappschussen zerlegt, die Schritt fur Schritt durchdacht werden konnen.
85
Erinnerung: Algorithmus mu auch wohldeniert laufen und terminieren!
Einzige Gefahr fur wohldenierten Lauf bei diesem
Algorithmus: Arithmetischer U berlauf bei der Addition.
Beobachtung: Falls fib(n) mit Java{Datentyp
int
Informatik II { Sommersemester 1999
Termination:
Eigentlich trivial bei reinen Zahlscheifen wie hier:
for ( int i = 3; i <= n; i++ )
Achtung: Frage nicht zu fruh als erledigt betrachten!
darstellbar ist, kann auch bei den Zwischenergebnissen
kein U berlauf passieren, da alle Zwischenergebnisse im
Bereich [0; : : : ; fib(n)] liegen.
Beliebte Tippfehler:
Maximal darstellbare Zahl:
231 ; 1 = 2:147:483:647.
;! Fur n 46 lauft der Algorithmus
wohldeniert.
Informatik II { Sommersemester 1999
87
86
for ( int i = 3; i >= n; i++ )
;! falschlich sofortiger Abbruch fur n > 3.
for ( int i = 3; i <= n; i-- )
for ( int i = 3;
; i++ )
;! arithmetischer U berlauf.
for ( int i = 3; i <= n; )
;! Endlosschleife fur n 3.
Informatik II { Sommersemester 1999
88
Mathematische Exkursion: Korrektheit von Algorith-
Merke:
men und vollstandige Induktion.
Aus gut gewahlten Schleifeninvarianten und
Standardbeispiel zur Erinnerung:
-varianten lat sich die Idee eines Algorithmus
verstehen und seine Korrektheit im Prinzip
auch beweisen.
Faustregel:
{ Schleifenvarianten sind gut gewahlt, wenn
aus ihnen leicht Termination ersichtlich ist.
{ Schleifeninvarianten sind gut gewahlt,
wenn aus der Aussage der Schleifeninvarianten fur den allerletzten Durchlauf durch
die Schleife unmittelbar folgt, da die Ausgabe des Algorithmus korrekt ist.
Allerdings mu noch gepruft werden, ob alle
Details der Implementation wirklich mit dem
"gedachten\ Algorithmus ubereinstimmen.
Informatik II { Sommersemester 1999
Beobachtungen:
i=1
i = n(n2+ 1)
Behauptung ist wahr fur n = 1.
Falls Behauptung fur irgendein n wahr ist, dann
auch fur m := n + 1, denn:
m
X
i=1
i=
n
X
i=1
i + (n + 1)
= n(n + 1) + (n + 1)
!
2
= n(n + 1) +2 2(n + 1)
= (n + 1)(2 n + 2) = m(m2+ 1)
89
Idee der vollstandigen Induktion:
Behauptung ist wahr fur n = 1
;! auch fur n = 2
;! auch fur n = 3
;! auch fur n = 4
:::
;! auch fur n = 3:796:541
:::
Informatik II { Sommersemester 1999
90
Merke:
Schleifeninvarianten werden grundsatzlich
Gliederung eines Beweises mit vollstandiger Induktion:
Induktionsverankerung: Beweise, da die Behaup-
tung fur n = 1 wahr ist.
Induktionsschritt: Beweise, da die Behauptung fur
n + 1 wahr ist, unter der Voraussetzung, da sie fur
n wahr ist.
Informatik II { Sommersemester 1999
n
X
91
durch vollstandige Induktion bewiesen (auch
dann, wenn man diese vollstandige Induktion
nicht explizit ausformuliert).
Die Gultigkeit der Schleifeninvarianten im ersten Durchlauf ist gerade die Induktionsverankerung. Die Korrektheit der Verankerung
ergibt sich aus den Initialisierungen vor der
Schleife.
Der Induktionsschritt beweist die Gultigkeit
der Schleifeninvarianten fur den Durchlauf Nr.
k +1 unter der Voraussetzung, da die Schleifeninvarianten fur den Durchlauf Nr. k wahr
sind.
Informatik II { Sommersemester 1999
92
Abschlieender Ausblick:
Es gibt algorithmische Problemstellungen, fur die
mit mathematischer Strenge bewiesen werden kann,
da es keinen Losungsalgorithmus geben kann.
Dazu gehort zum Beispiel die algorithmische Problemstellung
prufe ob ein beliebig gegebenes
"Java{Programm
korrekt ist\.
Details: Vorlesung Theoretische Informatik
Unuberwindliche Hurde: Die entscheidenden Schleifeninvarianten und -varianten konnen nicht algorithmisch aus dem Quelltext rekonstruiert werden.
Moglicher Ausweg in der Zukunft: neue Programmiersprachen, die die explizite Angabe aller notwendigen Schleifeninvarianten und -varianten vom
Programmierer erzwingen.
Informatik II { Sommersemester 1999
93
Entwurf von Algorithmen in Sicht.
;! Immer wieder Kreativitat erforderlich.
Grundidee fur eine mogliche Herangehensweise:
Erst die zentralen Schleifeninvarianten und
-varianten ausdenken.
Daraus dann den Algorithmus selbst entwickeln.
Fallbeispiel: zwei verschiedene Algorithmen fur das
Sortierproblem.
Eingabe: Array A von n Werten eines Datentyps,
auf denen eine Sortierreihenfolge "\ deniert ist.
Ergebnis: A ist sortiert gema "\.
Informatik II { Sommersemester 1999
94
Vollstandiger Algorithmus in Java:
Algorithmus I: "Selection{Sort\
(Sortieren durch direktes Auswahlen)
int indexOfMin (Object[] A, int first_index,
Comparator cmp)
{
int index = first_index;
for ( int i=first_index+1; i<A.length; i++ )
if ( cmp.is_less_than ( A[i], A[index] ) )
index = i;
return index;
}
Einfache Idee fur eine Schleifeninvariante:
Nach k Durchlaufen stehen in
A[0]; : : : ;A[k-1] die gem
a Sortierreihenfolge korrekten Elemente.
void swapComponents (Object[] A,
int index1, int index2)
{
Object x = A[index1];
A[index1] = A[index2];
A[index2] = x;
}
;! Algorithmisches Vorgehen ist (fast) oensichtlich: Vertausche A[k-1] mit
minfA[k-1]; : : : ; A[A.length-1]g
im k{ten Durchlauf.
Informatik II { Sommersemester 1999
Thema 5: Entwurf von Algorithmen
Grundproblem: Kein "Algorithmus\ zum
void sort (Object[] A, Comparator cmp)
{
for ( int i=0; i<A.length; i++ )
{
int index = indexOfMin (A, i, cmp);
swapComponents (A[i], A[index]);
}
}
95
Informatik II { Sommersemester 1999
96
Algorithmus II: "Mergesort\
Zahlenbeispiel:
(Sortieren durch Verschmelzen)
Schleifeninvariante:
21 17 41 67 41 12 15 23 88 9 27 44 18 11 4 36
Nach k Durchlaufen sind jeweils
2k aufeinanderfolgende Elemente
untereinander korrekt sortiert.
21 17
17 21
Etwas genauer formuliert:
Sei n :=A.length.
Fall, da n eine Zweierpotenz ist, d.h. n = 2m fur
ein m 2 N .
Das Intervall f0; : : : ; n ; 1g wird fur den k{ten
Durchlauf in 2m;k Abschnitte der Lange 2k zerlegt.
Die Reihenfolge der Elemente innerhalb eines dieser
Abschnitte soll am Ende des k{ten Durchlaufs der
Sortierreihenfolge entsprechen.
97
Oenes Problem: ezient zwei sortierte Sequenzen
der Lange 2k;1 zu einer sortierten Sequenz der Lange
2k verschmelzen.
;! Eigenstandiges algorithmisches Problem.
Beobachtung: Algorithmus fur's Verschmelzen wird
wohl im Kern wieder eine Schleife sein.
;! Wieder uber Schleifeninvarianten und
-varianten nachdenken.
41 67
12 41
15 23
12 15 23 41
12 15 17 21 23 41 41 67
4
23 88
9
9 88
27
44 18
27 44
9 27 44 88
11
11 18
4
36
4 36
4 11 18 36
4 9 11 18 27 36 44 88
9 11 12 15 17 18 21 23 27 36 41 41 44 67 88
Informatik II { Sommersemester 1999
98
Mogliche Umsetzung:
Ein Hilfsarray der Lange 2k wird angelegt.
Die Elemente der beiden zu verschmelzenden Teil-
sequenzen werden Schritt fur Schritt in sortierter
Reihenfolge in das Hilfsarray kopiert.
Dann wird der Inhalt des Hilfsarrays in die 2k Komponenten im eigentlichen Array zuruckkopiert.
Idee fur sortierte Kopie in das Hilfsarray:
Idee fur Schleifeninvariante:
{ Zwei aktuelle Indizes j1 und j2 zeigen an, bis zu
welchem Element jede der beiden Teilsequenzen
schon kopiert wurde.
{ Das kleinere der beiden durch j1 und j2 angezeigten Elemente wird jeweils als nachstes kopiert.
{ Bei zwei gleichen Elementen: egal.
Nach i Durchlaufen sind die ersten
i der insgesamt 2k Positionen der
Sequenz mit den dort hingehorenden Elementen besetzt.
Informatik II { Sommersemester 1999
67 41 12 15
17 21 41 67
Zur Vereinfachung betrachten wir zunachst nur den
Informatik II { Sommersemester 1999
41
99
Informatik II { Sommersemester 1999
100
Zahlenbeispiel:
Fortsetzung Zahlenbeispiel:
j1
j2
17 21 41 67
12 15 23 41
j1
j2
17 21 41 67
12 15 23 41
j1
j2
17 21 41 67
12 15 23 41
j2
j1
17 21 41 67
12 15 23 41
j1
17 21 41 67
j1
i
j2
12 15 23 41
i
j1
j2
17 21 41 67
12 15 23 41
i
j1
12 15
17 21 41 67
17 21 41 67
i
12 15 17 21 23 41
j2
i
12 15 17 21 23 41 41
j2
12 15 23 41
i
12 15 17 21 23 41 41 67
i
12 15 17 21
101
Notation:
Sei 0; : : : ; 2k;1
; 1 der Indexbereich der beiden
Teilsequenzen sowie
0; : : : ; 2k ; 1 der Indexbereich der "verschmolzenen\
Sequenz.
Schleifeninvarianten nach dem h{ten Durchlauf:
i = j1 + j2 = h.
Die Elemente 0; : : : ; j1 ; 1 der ersten und die Elemente 0; : : : ; j2 ; 1 der zweiten Teilsequenz sind in
sortierter Reihenfolge an den Indizes 0; : : : ; i ; 1 der
verschmolzenen Sequenz gespeichert.
Element j1 der ersten Teilsequenz ist groer/gleich
Element j2 ; 1 der zweiten Teilsequenz.
Element j2 der zweiten Teilsequenz ist analog
groer/gleich Element j1 ; 1 der ersten Teilsequenz.
Informatik II { Sommersemester 1999
12 15 17 21 23
12 15 23 41
j1
i
12 15 17
i
12 15 23 41
12
Informatik II { Sommersemester 1999
j2
17 21 41 67
103
Informatik II { Sommersemester 1999
102
Fehlt noch: Der Fall, da n keine Zweierpotenz ist.
Notation: Sei 2m die kleinste Zweierpotenz
mit n 2m.
Erste mogliche Vorgehensweise:
Hilfsarray mit 2m Elementen anlegen.
Werte von A in das Hilfsarray kopieren.
Rest des Hilfsarrays mit 2m ; n "Dummy{Werten\
auullen.
Obigen Sortieralgorithmus auf das Hilfsarray anwenden.
Alle "Nicht{Dummy{Werte\ aus dem Hilfsarray in
sortierter Folge zuruckkopieren.
Informatik II { Sommersemester 1999
104
Zahlenbeispiel mit "Dummy{Wert\ 0:
Zweite mogliche Vorgehensweise: In jedem Durchlauf ist potentiell die letzte Teilsequenz unvollstandig
und wird gesondert, aber analog behandelt.
21 -8 41 67 41 12 -3 23 88 0 27
21 17 41 67 41 12 15 23 88 9 27
21 -8 41 67 41 12 -3 23 88 0 27 0 0
0 0
21 17
0
17 21
Sortieren
-3 -8 0 0
0 0
0
41 67 41 12 15
41 67
17 21 41 67
0 12 21 23 27 41 41 67 88
12 41
15 23
12 15 23 41
12 15 17 21 23 41 41 67
-3 -8 0 12 21 23 27 41 41 67 88
Informatik II { Sommersemester 1999
9
9 88
27
27
9 27 88
9 27 88
9 12 15 17 21 23 27 41 41 67 88
105
Weiteres, ahnlich gelagertes Fallbeispiel:
Informatik II { Sommersemester 1999
106
Nun Ziel: Fur Mengen A und B mit einer solchen
Ordnung "\ einen massiv ezienteren Algorithmus
entwickeln.
Schnittmenge berechnen
Gegeben: Zwei endliche Mengen A und B .
Gesucht: Schnitt A \ B .
A
23 88
;! Einschrankung auf geordnete Mengen A und
B ist weiteres sinnvolles Beispiel fur algo-
rithmenorientierte Denitionen von algorithmischen Problemstellungen (vgl. Thema 1 der
Vorlesung).
B
Primitive Idee: Alle Elemente von A durchgehen und
nachschauen, ob das Element jeweils in B enthalten
ist.
;! jAj jB j Tests auf Gleichheit von Elementen.
Annahme zur Vereinfachung: A und B sind "richtige\ Mengen, d.h. alle Elemente von A sind paarweise
verschieden (ebenso alle Elemente von B untereinander).
Hilfreiche Einsicht: In der Praxis haben A und B
meist gleichen Elementtyp, und man kann meist eine
Ordnung "\ auf diesem Typ denieren (bzw. ist sogar
schon vordeniert).
Informatik II { Sommersemester 1999
107
Informatik II { Sommersemester 1999
108
Erste Idee fur Schleifeninvarianten: Zwei Indizes i
und j durchlaufen A und B so, da
Notation:
A = fa0; a1; : : : ; am;1g mit
a0 a1 am;1.
immer ai;1 bj und bj;1 ai gilt und
alle Elemente von Ai \ Bj schon gefunden und
B = fb0; b1; : : : ; bn;1g mit
b0 b1 bn;1.
ausgegeben sind, aber noch kein Element von
(A n Ai) \ (B n Bj ).
Ai := fa0; : : : ; ai;1g fur i 2 f0; : : : ; mg
(insbesondere A0 = ; und Am = A).
Ai
Bj := fb0; : : : ; bj;1g fur j 2 f0; : : : ; ng
(insbesondere B0 = ; und Bn = B ).
i
A
2 3
B
2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56
5
7 11 13 17 19 23 29 31 37 41 43 47 53
j
Bj
Informatik II { Sommersemester 1999
109
Beobachtung: Aus der ersten Schleifeninvariante folgt
Ai \ (B n Bj ) = Bj \ (A n Ai) = ;.
Konsequenz:
A \ B = (Ai \ Bi) [ ((A n Ai) \ (B n Bj )),
d.h. der Algorithmus "erwischt\ tatsachlich alle Elemente von A \ B .
Informatik II { Sommersemester 1999
Einfache Umsetzung:
int i
int j
while
{
if
{
A
B
2
2
3
5
5
= 0;
= 0;
( i < m && j < n )
( A[i] == B[j] )
System.out.println ( A[i] );
i++;
j++;
}
else if ( A[i] < B[j] )
i++;
else // A[i] > B[j]
j++;
}
Schleifenvariante: In jedem Durchlauf wird i oder j
(oder beide) um 1 erhoht.
Ai
110
i
Ai
7 11 13 17 19 23 29 31 37 41 43 47 53
i
A
2
3 5
B
2
5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56
7 11 13 17 19 23 29 31 37 41 43 47 53
8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56
Bj
j
j
Bj
Informatik II { Sommersemester 1999
111
Informatik II { Sommersemester 1999
112
Beachte: Erste Idee zu Schleifeninvarianten sagt nichts
uber den Fall i = m oder j = n aus.
Konkretisierte Schleifeninvarianten: Vor und nach
jedem Schleifendurchlauf existieren zwei aktuelle Indizes i 2 f0; : : : ; mg und j 2 f0; : : : ; ng, so da
ai;1 bj und bj;1 ai im Falle i < m; j < n gilt
und
alle Elemente von Ai \ Bj schon gefunden und
ausgegeben sind, aber noch kein Element von (A n
Ai) \ (B n Bj ).
Korrektheitsbeweis:
Termination: Aufgrund der Schleifenvariante nach
maximal m + n Durchlaufen.
Wohldeniertheit: Durch die Abbruchbedingung der
while{Schleife ist garantiert, da nur auf existierende Komponenten von A und B zugegrien wird.
Korrektes Ergebnis: Am Ende des Algorithmus gilt
i = m oder j = n (oder beides).
;! A n Ai = ; oder B n Bj = ;.
;! (A n Ai) \ (B n Bj ) = ;.
;! Ai \ Bj = A \ B .
;! Die Schleifeninvariante beweist, da
am Ende genau A \ B ausgegeben worden ist.
Frage: Wo wird eigentlich die Annahme gebraucht,
da alle Elemente paarweise verschieden sind?
Informatik II { Sommersemester 1999
113
Antwort: in der Schleifeninvariante.
Gegenbeispiel fur den Fall, da die Annahme nicht
zutrit:
2
3
B
2
5 8 11 14 17 20 20 26 29 32 35 38 41 44 47 50 53 56
Bj
Hatte man selbst bei der Formulierung des Algorithmus und beim Korrektheitsbeweis an die
Annahme und ihre wesentliche Bedeutung fur die
Korrektheit der Schleifeninvariante gedacht!?
i
A
5
114
Unangenehme Frage:
und nach jedem Schleifendurchlauf gibt es
"Vor aktuelle
zwei
Indizes i 2 f0; : : : ; mg und j 2
f0; : : : ; ng, so da ai;1 bj und bj;1 ai im
Falle i < m; j < n gilt.\
Ai
Informatik II { Sommersemester 1999
7 11 13 17 20 20 29 31 37 41 43 47 53
j
;! Nach dem nachsten Vorwartsschritt wird
die Schleifeninvariante verletzt.
Informatik II { Sommersemester 1999
115
Informatik II { Sommersemester 1999
116
Thema 6: Rekursive Algorithmen
Beobachtung: Viele Funktionen kann man
Merke:
Die Schleifenvarianten und -invarianten eines
iterativ und rekursiv denieren.
Algorithmus sind in gewisser Weise seine "Essenz\.
Entwurf von Algorithmen ist (und bleibt wohl
auch) eine kreative Tatigkeit, fur die es kein
Kochrezept gibt.
Oft ist es einfacher, eine intuitive Idee fur die
algorithmische Vorgehensweise zuerst in eine
solche "Essenz\ umzusetzen und daraus dann
den eigentlichen Algorithmus zu konstruieren.
Beispiel: Fakultat.
Iterative Denition: n! = 1 2 (n ; 1) n.
Rekursive Denition:
n! = 1 fur n = 1 bzw.
n! = n (n ; 1)! fur n > 1.
Iterative Denition implementieren:
Insbesondere hat man dabei den Korrektheits-
int faculty ( int n )
{
int result = 1;
for ( int i = 2; i <= n; i++ )
result *= i;
return result;
}
beweis fur den Algorithmus gleich mitkonstruiert.
Informatik II { Sommersemester 1999
117
Nun rekursive Denition implementieren:
Informatik II { Sommersemester 1999
118
Experiment:
int faculty ( int n )
{
if ( n == 1 )
return 1;
return n * faculty ( n - 1 );
}
Beobachtung: Es spricht prinzipiell zunachst einmal
nichts dagegen, da eine Methode auch "sich selbst\
aufrufen kann.
public static void myRecursiveMethod ( int n )
{
if ( n == 0 )
return;
System.out.print ( n );
System.out.print ( " " );
myRecursiveMethod ( n - 1 );
System.out.print ( n );
System.out.print ( " " );
}
...
myRecursiveMethod ( 5 );
Ausgabe: 5 4 3 2 1 1 2 3
Frage: Was geht da vor sich!?
Informatik II { Sommersemester 1999
119
Informatik II { Sommersemester 1999
4 5
120
Erklarung:
Wann immer eine Methode aufgerufen wird, wird
intern neuer Speicherplatz fur die Daten des Aufrufs
angelegt (u.a. fur jeden Parameter).
Am Ende des Aufrufs wird der Speicherplatz wieder
freigegeben,
Es sind immer nur die Daten des letzten Aufrufs
sichtbar.
;! Wahrend des 5. und tiefsten rekursiven
Aufrufs von myRecursiveMethod im Beispiel gibt es insgesamt 5 verschiedene,
vollig voneinander unabhangige Speicherplatze mit Namen n.
5
4
3
2
1
n
n
n
n
Informatik II { Sommersemester 1999
void f ( int n )
{
System.out.println ( n );
f ( n - 1 );
}
Ergebnis: Nach Ausgabe eines gewissen Wertes n gibt
es Programmfehler!
Erlauterung:
Fur die Gesamtdaten aller Methodenaufrufe eines
Daten zum 1. 2. 3. 4. 5. rekursiven Aufruf
n
Vorsicht: Rekursion ohne Abbruch!
121
Abschreckendes Beispiel: Fibonacci{Zahlen
Programms ist nur ein gewisser kleiner Speicherplatz
reserviert.
Bei einer Rekursion ohne Abbruch wird diese Grenze
naturlich irgendwann uberschritten.
Informatik II { Sommersemester 1999
122
Frage: Was ist das Problem?
Antwort: Die ganzen Zwischenergebnisse fib(1),
fib(2); : : : ; fib(n) werden immer und immer wieder
Erinnerung:
fib(1) = fib(2) = 1,
fib(n) = fib(n ; 1) + fib(n ; 2) fur n > 2.
neu berechnet (und wieder vergessen).
Umsetzung als rekursive Methode:
fib (6)
int fibonacci ( int n )
{
if ( n <= 2 )
return 1;
else
return fibonacci (n-1) + fibonacci (n-2);
}
fib (5)
fib (4)
Beobachtung:
Fur n = 30 wird die Laufzeit schon spurbar.
Fur n = 40 dauert es eeeeewig.
fib (3)
Kontrast: Beim iterativen Algorithmus aus Thema 4
der Vorlesung ist das Ergebnis auch bei n = 40
sofort da.
Informatik II { Sommersemester 1999
123
fib (2)
fib (2)
fib (4)
fib (3)
fib (2)
fib (1)
fib (3)
fib (2)
fib (2)
fib (1)
fib (1)
Informatik II { Sommersemester 1999
124
n
Konkret:
Notation: g(n) Gesamtzahl der Aufrufe von
fibonacci f
ur Eingabe n.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Beobachtung:
g(1) = g(2) = 1,
g(n) = g(n ; 1) + g(n ; 2) + 1 fur n > 2.
Einsicht: g(n) = 2 fib(n) ; 1 fur n 2.
Begrundung mit vollstandiger Induktion:
n = 2: Oensichtlich.
n > 2: g(n) = g(n ; 1) + g(n ; 2) + 1
= [2 fib(n ; 1) ; 1] + [2 fib(n ; 2) ; 1] + 1
= 2 fib(n) ; 1.
Informatik II { Sommersemester 1999
g(n)
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
1
1
3
5
9
15
25
41
67
109
177
287
465
753
1219
20
6:765
13:529
30
832:040
1:664:079
:::
:::
:::
:::
:::
:::
:::
:::
:::
40 102:334:155 204:668:309
125
Kontrast: Beim iterativen Algorithmus wurde jedes
der n Zwischenergebnisse genau einmal berechnet.
Erinnerung (Vorlesungsthema 4):
int fibonacci (
{
if ( n <= 2
return 1;
int x;
int y = 1;
int z = 1;
for ( int i
{
x = y;
y = z;
z = x +
}
return z;
}
fib(n)
Informatik II { Sommersemester 1999
126
... Wozu eigentlich Rekursion!?
Antwort: Rekursive Algoritmen sind oft sehr viel einfacher und auch naher an den dahinterstehenden abstrakten Ideen.
Beispiel: Mergesort (vgl. Vorlesungsthema 5)
int n )
)
21 17 41 67 41 12 15 23 88 9 27 44 18 11 4 36
21 17
41
67
41 12
41 67
12 41
15
23
88
9
27
44 18
11
4
36
= 3; i <= n; i++ )
17 21
17 21 41 67
y;
15 23
12 15 23 41
12 15 17 21 23 41 41 67
4
9 88
27 44
9 27 44 88
11 18
4 36
4 11 18 36
4 9 11 18 27 36 44 88
9 11 12 15 17 18 21 23 27 36 41 41 44 67 88
Frage: Wozu dann eigentlich Rekursion???
Informatik II { Sommersemester 1999
127
Informatik II { Sommersemester 1999
128
Rekursive Formulierung:
void sortRecursively ( Object[] A, Comparator cmp,
int first, int last )
{
if ( first == last )
return;
int middle = ( first + last ) / 2;
sortRecursively ( A, cmp, first, middle );
sortRecursively ( A, cmp, middle+1, last );
merge ( A, cmp, first, middle, last );
}
void sort ( Object[] A, Comparator cmp )
{
sortRecursively ( A, cmp, 0, A.length-1 );
}
Abstrakte Idee von Mergesort:
Zerlege die zu sortierende (Teil-)Sequenz in zwei
Teilsequenzen durch ungefahre Halbierung.
Sortiere beide Teilsequenzen in sich.
Verschmelze die nun sortierten zwei Teilsequenzen
zu einer insgesamt sortierten.
;! Rekursiver Algorithmus ist fast schon die
wortliche Umsetzung dieser abstrakten
Idee.
Erlauterung: Methode merge ist hier ausgelassen worden und soll das Verschmelzen der sortierten Teilsequenzen A[left]...A[middle] und
A[middle+1]...A[last] zu einer sortierten Teilsequenz A[first]...A[last] leisten.
;! Vgl. Thema 5 der Vorlesung.
Informatik II { Sommersemester 1999
129
U blicher Trick: Den eigentlich rekursiven Algorithmus
in eine eigene Methode auslagern.
Warum: Die Rekursion basiert haug auf zusatzlichen
Parametern, die in der eigentlichen algorithmischen
Problemstellung nur implizit auftreten.
Beispiel von oben: Anfang und Ende der zu sortierenden Teilsequenz.
void sortRecursively ( Object[] A, Comparator cmp,
int first, int last )
{
...
}
Informatik II { Sommersemester 1999
130
Weiteres Beispiel: Formalsprachliche
Ausdrucke auswerten.
Konkretes Beispiel:
4 + (3 + 2) (4=(6 ; (8 4 + (2 ; 3))))
+
4
*
+
3
/
2
-
4
6
+
void sort ( Object[] A, Comparator cmp )
{
sortRecursively ( A, cmp, 0, A.length-1 );
}
8
Informatik II { Sommersemester 1999
-
*
131
Informatik II { Sommersemester 1999
4
2
3
132
Umsetzung:
Abstrakte Idee fur rekursive Auswertung:
Falls Ausdruck eine einzelne Zahl...
;! Wert des Ausdrucks = Zahl.
Falls ganzer Ausdruck in Klammern...
;! Vergi die Klammern.
In jedem anderen Fall sollte es mindestens einen
binaren Operator (also Plus, Minus, Mal, Durch)
auf hochster Stufe auerhalb aller Klammern geben.
{ Falls es mindestens ein Plus oder Minus auf
hochster Stufe gibt: Brich den Ausdruck am linkesten Plus oder Minus auf ("Punkt vor Strich\!).
{ Sonst: Brich den Ausdruck am linkesten Mal oder
Durch auf.
Informatik II { Sommersemester 1999
Methode evaluate
133
branched:
public double evaluate ( String expr )
throws IllFormedExpression
{
if ( isDoubleNumber (expr) )
return convertToDouble (expr);
int index;
double value;
if ( plusOrMinusOnHighestLevel (expr) )
{
index = findFirstPlusOrMinusOnHighestLevel (expr);
value = evaluate_branched ( expr, index );
}
else if ( timesOrDivOnHighestLevel (expr) )
{
index = findFirstTimesOrDivOnHighestLevel (expr);
value = evaluate_branched ( expr, index );
}
else if ( expr[0]=='(' && expr[expr.length()-1]==')' )
{
String realExpr
= expr.substring ( 1, expr.length()-2 );
value = evaluate ( realExpr );
}
else
throw new IllFormedExpression();
return value;
}
Informatik II { Sommersemester 1999
134
Weitere zu leistende Vorarbeiten fur eine solche
Umsetzung auf hoher Abstraktionsebene (hier ausgelassen):
public double evaluate_branched
( String expr, int index )
throws IllFormedExpression
Test ob expr eine einzelne reelle Zahl ist:
{
String expr1 = expr.substring (0,index-1);
String expr2
= expr.substring (index+1,expr.length()-1);
double value1 = evaluate (expr1);
double value2 = evaluate (expr2);
char operator = expr[index];
if ( operator == '+' )
return value1 + value2;
if ( operator == '-' )
return value1 - value2;
if ( operator == '*' )
return value1 * value2;
if ( operator == '/' )
return value1 / value2;
boolean isDoubleNumber (String expr)
Berechnung dieser reellen Zahl:
double convertToDouble (String expr)
Test ob es auf hochster Stufe ein Plus oder Minus
gibt (timesOrDivOnHighestLevel analog):
double plusOrMinusOnHighestLevel (String expr)
}
Beobachtung: Zwei Methoden konnen sich auch ge-
genseitig rekursiv aufrufen.
Falls ja, Lieferung des Index des "linkesten\ Plus
oder Minus (findFirstTimesOrDivOnHighestLevel
analog):
int findFirstPlusOrMinusOnHighestLevel (String expr)
Informatik II { Sommersemester 1999
135
Informatik II { Sommersemester 1999
136
Weitere Zusatzarbeit:
Exception{Klasse IllFormedExpression zur Anzeige, da der Ausdruck in expr nicht den Regeln entspricht.
Korrektheit rekursiver Algorithmen
Erinnerung: Hauptkonzept bei iterativen Algorithmen
waren Schleifenvarianten und Schleifeninvarianten.
;! Korrektheitsbeweis durch vollstandige In-
duktion uber die Anzahl der Schleifendurchlaufe.
Rekursiver Fall:
Frage: Klingt das alles etwa kompliziert?
Wieder mittels vollstandiger Induktion.
Nun aber uber die Rekursionsparameter.
Antwort:
Schon moglich.
Eine iterative Formulierung ware aber wohl massiv
komplizierter!
Informatik II { Sommersemester 1999
137
Beispiel Mergesort:
Methode sort als rekursive Formulierung von Mer-
gesort lost das Problem oensichtlich korrekt, sofern
Hilfsmethode sortRecursively korrekt ist.
Rekursionsinvariante: Methode sortRecursively
lost das Problem fur n 1 zu sortierende Elemente
korrekt.
Rekursionsvariante: Bei jedem rekursiven Aufruf
wird die Anzahl der zu sortierenden Elemente verkleinert.
;! Endliche maximale Rekursionstiefe.
Informatik II { Sommersemester 1999
Rekursionsinvariante: Methode
138
sortRecursively
lost das Problem korrekt, wenn
Unterprogramm merge korrekt ist und
sortRecursively das Problem fur beliebige m < n
zu sortierende Elemente korrekt lost.
;! Induktionsschritt.
Beobachtung: Korrektheit von Induktionsanfang und
Induktionsschritt ergeben sich (fast) trivial aus der
rekursiven Beschreibung von Mergesort (vorausgesetzt,
merge ist korrekt).
Beweise der Rekursionsvariante: In diesem Fall trivial.
;! Nur Invariante zu betrachten.
Informatik II { Sommersemester 1999
139
Informatik II { Sommersemester 1999
140
Beobachtung: Jeder iterative Algorithmus lat sich
auf einfache Weise in einen rekursiven umformulieren.
Beispiel Auswertung von Ausdrucken:
Rekursionsvariante: Bei jedem rekursiven Aufruf verringert sich die Anzahl der Zeichen im Ausdruck.
;! Endliche Rekursionstiefe.
Iterativer Algorithmus:
Rekursionsinvariante: Ein Ausdruck mit n Zeichen
wird korrekt behandelt.
{ Induktionsanfang: Korrektheit der Methoden
isDoubleNumber und convertToDouble.
{ Induktionsschritt: evaluate is korrekt fur Ausdrucke mit n > 1 Zeichen, wenn das Ergebnis
von evaluate fur einen beliebigen Ausdruck mit
weniger als n Zeichen korrekt ist.
Beobachtung: Unter der Annahme, da die ausgelassenen Hilfsmethoden korrekt sind, sind Induktionsanfang und Induktionsschritt wieder (fast) trivial.
Informatik II { Sommersemester 1999
Idee am einfachen Beispiel:
141
void iteratively ( int n )
{
for ( int i = 0; i <= n; i++ )
System.out.println (i);
}
Rekursiv derselbe Eekt:
void recursively ( int n )
{
if ( n < 0 )
return;
recursively ( n - 1 );
System.out.println (n);
}
Informatik II { Sommersemester 1999
142
Thema 7: Asymptotische Ezienz von
Algorithmen
Merke:
Fur jedes Problem, fur das es iterative Algo-
Naive\ Denition: Die Ezienz eines Algorithmus
"besagt,
welche Laufzeit er bis zur Termination ver-
rithmen gibt, gibt es auch rekursive Algorithmen.
Neben den rekursiven Algorithmen, die man
direkt aus den iterativen konstruieren kann,
gibt es bei vielen Problemstellungen auch weitere rekursive Algorithmen, die einfacher und
intuitiver als jeder iterative Algorithmus sind.
Auch der Korrektheitsbeweis ist dann meist
einfacher und intuitiver.
Allerdings sind solche rekursiven Algorithmen
haug (nicht immer!) weniger ezient als die
ezientesten iterativen.
braucht.
Problem: Diese Denition von Ezienz hangt ab von
der gewahlten Programmiersprache,
der gewahlten Plattform (Hardware, Betriebssystem
und Compiler),
den anderen momentan auf dem System laufenden
Prozessen,
den diversen kleinen technischen Details der Implementation des Algorithmus.
Geugeltes Wort: "It depends on your system, your
hardware, and the phase of the moon.\
Informatik II { Sommersemester 1999
143
Informatik II { Sommersemester 1999
144
Erinnerung:
Erinnerung (Vorlesungsthema 5):
sung schon mehrfach verglichen.
"The phase of the moon\ etc. wurde dabei aber
nicht thematisiert.
Mengen A und B : Jedes Element von A mit jedem Element von B vergleichen.
Wenn es eine Ordnung "\ auf den Elementen von
A und B gibt: Ein gemeinsamer Durchlauf durch
beide Mengen in "\{Reihenfolge reicht aus.
Die Ezienz von Algorithmen wurde in der Vorle-
Fragen:
1. Welche Aspekte wurden statt dessen thematisiert?
2. Inwieweit war die Betrachtung dieser Aspekte eigentlich gerechtfertigt???
Konkretes Beispiel: Wie wurden noch 'mal die bei-
den Algorithmen zur Schnittmengenberechnung verglichen?
Informatik II { Sommersemester 1999
145
Schlufolgerung seinerzeit in Vorlesung war: 2. Algorithmus ist klar besser.
Fragen:
War diese Schlufolgerung gerechtfertigt?
Wenn ja: inwieweit eigentlich?
Und was sind die Gesetzmaigkeiten hinter dieser
Allgemeiner Algorithmus fur den Schnitt zweier
Ai
i
A
2
3
5
B
2
5
8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56
7 11 13 17 19 23 29 31 37 41 43 47 53
j
Bj
Konsequenz: Bei "unscharfem Hinsehen\ ist die An-
zahl der Operationen beim ersten Algorithmus proportional zu jAj jB j und beim zweiten proportional zu
jAj + jB j.
Informatik II { Sommersemester 1999
146
Beobachtung:
Wenn jAj oder jB j sehr klein ist, gilt
jAj jB j jAj + jB j.
Aber wenn sowohl jAj als auch jB j eine gewisse
Grenze uberschritten haben, geht es rapide und
ohne ein Halten aufwarts mit
jAj jB j
jAj + jB j
doch eher intuitiven Schlufolgerung?
Mathematisch ausgedruckt: Wenn jAj und jB j ins
Konkretere Fragen:
Unendliche wachsen, wachst auch
Worin besteht der Unterschied zwischen
jAj jB j und jAj + jB j?
Und wie wirkt er sich praktisch aus?
jAj jB j
jAj + jB j
ins Unendliche, also
lim
jAj jB j = 1
jAj; jBj;!1 jAj + jB j
Informatik II { Sommersemester 1999
147
Informatik II { Sommersemester 1999
148
Also: Anscheinend haben wir intuitiv den Fall, da jAj
und jB j nicht extrem klein sind, als Mastab genommen.
Rechtfertigung:
Bei kleinem jAj oder jB j ist die Ezienz
Anderes Beispiel: Sortieren von n Elementen
Erinnerung: Der einfache Algorithmus "Selection{
Sort\ vertauscht im i{ten Durchlauf der Hauptschleife
das Element A[i-1] mit dem kleinsten Element aus
A[i-1], A[i], A[i+1]...A[n-1].
nicht so kritisch.
Der Unterschied zwischen jAj jB j und
jAj + jB j ist bei kleinen Werten jAj oder
jB j nicht so dramatisch wie bei groen.
Konsequenz:
Die Laufzeit fur den i{ten Durchlauf ist ungefahr
proportional zu n ; i + 1.
Die Laufzeit des gesamten Algorithmus ist also un-
Konsequenzen:
In erster Linie wird von jetzt an das Verhalten von
gefahr proportional zu
n
X
n
X
i=1
i=1
Algorithmen fur groe Eingaben als Vergleichsmastab genommen.
Aber die kritische Frage, ob das jetzt in einem
konkreten Fall wirklich der adaquate Mastab ist,
bleibt im Hinterkopf.
;! Groenordnung n2.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
149
Zum Vergleich: Mergesort
17 21
41
67 41 12 15
41 67
17 21 41 67
12 41
12 15 23 41
12 15 17 21 23 41 41 67
4
23 88
15 23
150
zen zweier sortierter Teilsequenzen aus Thema 5 ist die
Laufzeit fur die Verschmelzung zweier Teilsequenzen
mit k und ` Elementen ungefahr proportional zu k + `.
9
9 88
27
44 18
27 44
9 27 44 88
11
11 18
4
36
4 36
;! Der Aufwand "pro Schicht\ ist proportio-
nal zur Zahl n der insgesamt zu sortierenden Elemente, da paarweise disjunkte
Teilsequenzen in jeder Schicht behandelt
werden.
;! Der Gesamtaufwand ist proportional zu
4 11 18 36
n mal der Anzahl Schichten.
4 9 11 18 27 36 44 88
Also Frage: Wieviele Schichten braucht
Mergesort, um n Elemente zu sortieren?
9 11 12 15 17 18 21 23 27 36 41 41 44 67 88
Informatik II { Sommersemester 1999
i = n(n2+ 1) 21 n2
Beobachtung: Mit dem Algorithmus zum Verschmel-
21 17 41 67 41 12 15 23 88 9 27 44 18 11 4 36
21 17
(n ; i + 1) =
151
Informatik II { Sommersemester 1999
152
Beobachtung: Zur besseren U bersicht betrachtet man
besser nur die Zweierpotenzen.
Resultat: Die Anzahl Schichten verhalt sich ungefahr
zu n wie k zu 2k .
n Anzahl Schichten
Exponent
1
2
1
2
4
2
8
3
3
4
16
4
32
5
5
6
64
6
128
7
7
8
256
8
9
512
9
10
1024
10
Umgekehrt formuliert: Die Anzahl Schichten ist ungefahr gleich log2(n).
;! Groenordnung der Gesamtlaufzeit ist
n log2(n).
Anschlufrage: Was bedeutet n log2(n) im
Verhaltnis zu n2 real?
;! Deutliches Ergebnis.
Informatik II { Sommersemester 1999
153
Umkehrtabelle gibt klare Antwort:
154
Frage: Kann man den Fall kleiner Groenordnungen
nicht vollig ignorieren?
n log2(n)
1
2
5
10
20
50
100
500
1:000
10:000
100:000
1:000:000
1:000:000:000
1:000:000:000:000
Informatik II { Sommersemester 1999
0
1
2
3
4
5
7
9
10
13
17
20
30
40
Antwort: Es gibt auch realistische Szenarien, in denen
es um sehr kleine Groenordnungen geht,
die Laufzeit des Algorithmus aber trotzdem nicht
vernachlassigt werden kann.
Konkret: Ein komplexer Algorithmus A hat als Teilprobleme eine groe Zahl kleiner Sequenzen zu sortieren.
;! Entscheidend fur die Laufzeit von A ist, wie
ezient der gewahlte Sortieralgorithmus bei
kleinen Eingaben ist.
;! n2 verhalt sich groenordnungsmaig zu
n log2 n wie Eeeewigkeit zu (beinahe)
Echtzeit.
Informatik II { Sommersemester 1999
155
Informatik II { Sommersemester 1999
156
Realistisches Szenario: Fur jede x{Koordinate (Kilometer) sortiere alle Orte auf dieser vertikalen Linie
untereinander nach ihren y{Koordinaten.
Merke:
Bei groen Eingaben konnen die Unterschiede
in der Laufzeit zweier Algorithmen fur dieselbe
Problemstellung dramatisch werden.
Es kommt sogar haug vor, da der Unterschied "ins Unendliche\ wachst.
Es ist daher zweckmaig, die Laufzeit eines
Algorithmus in erster Linie mittels sehr groer
Eingaben zu bewerten.
Allerdings gibt es auch Szenarien, in denen
dieses Kriterium nicht adaquat ist, weil eine
sehr groe Zahl kleiner Eingaben zu bearbeiten ist.
Informatik II { Sommersemester 1999
157
Informatik II { Sommersemester 1999
158
Thema 8: O{Notation
Ziel: Mathematischen Formalismus fur die Asymptotik
Problem: Bei exakt gleichen Werten dieser Kenn-
der Laufzeit von Algorithmen entwickeln.
groen kann die Laufzeit eines Algorithmus immer
noch stark variieren.
Das heit:
Beispiel:
Analysieren, was passiert, wenn die Eingaben sehr
gro werden.
Groe der Eingabe gemessen in einer oder wenigen
Kenngroen.
Beispiele fur Kenngroen aus Thema 5 der
Vorlesung:
T{Wert t.
A
eines Datentyps T, zusatzlicher
Gesucht: Information, ob t momentan in A gespeichert ist.
Algorithmus:
public boolean searchItemInArray ( T[] A, T t )
{
for ( int i = 0; i < A.length; i++ )
if ( A[i] == t )
return true;
return false;
}
Sortieren: Anzahl der zu sortierenden
Elemente.
;! 1 Kenngroe.
Schnittmenge: Groe der beiden zu
schneidenden Mengen.
;! 2 unabhangige Kenngroen.
Informatik II { Sommersemester 1999
Eingabe: Array
159
Informatik II { Sommersemester 1999
160
Naheliegende Kenngroe: A.length.
Beobachtung:
Terminologie:
Worst Case: Fur jede Kombination von Werten fur
zu A.length.
Im besten Fall ist das allererste Element schon das
gesuchte.
;! Die Laufzeit ist dann im Prinzip unabhangig von A.length.
die Kenngroen die maximale Laufzeit, die der Algorithmus fur eine Eingabe mit diesen Kenngroenwerten haben kann.
Best Case: Minimale Laufzeit analog zum Worst
Case.
Average case: Fur jede Kombination von Werten
fur die Kenngroen die durchschnittliche Laufzeit
"typischer\ Eingaben mit diesen Kenngroenwerten.
Konsequenzen:
Konsequenz:
fur die Laufzeit in Abhangigkeit von den Kenngroen
suchen.
Auch relevant: Die durchschnittliche Laufzeit des
Algorithmus fur "typische\ Eingaben (was immer
das heien mag...).
groen.
Average Case hingegen hangt noch zusatzlich davon
ab, was "typisch\ heien soll.
Im schlechtesten Fall wird A einmal durchlaufen.
;! Die Laufzeit ist ungefahr proportional
Nach oberen und unteren asymptotischen Schranken
Worst und Best Case sind Funktionen der Kenn-
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
161
162
Frage:
Formalisierung:
portional\ zu irgendwas charakterisiert.
Was soll denn das genau heien?
Es gibt zwei Konstanten c1 > 0 und c2 > 0, so da fur
alle Werte von n1; : : : ; nk gilt:
f1(n1; : : : ; nk) c1 f2(n1; : : : ; nk) und
f2(n1; : : : ; nk) c2 f1(n1; : : : ; nk).
Bisher wurden Laufzeiten immer als "ungefahr pro-
Abstrakte Idee:
Seien n1; : : : ; nk 2 N die Kenngroen fur eine algorithmische Problemstellung.
Seien f1; f2 : N k ;! N zwei Funktionen in den k
Kenngroen.
Dann sollen f1 und f2 als "ungefahr proportional\
angesehen werden, wenn sie nur in einer gewissen (multiplikativen) Bandbreite voneinander abweichen.
Informatik II { Sommersemester 1999
163
c2 . f1
f1
f2
1 .
f
c1 1
Informatik II { Sommersemester 1999
164
Terminologie:
Wenn f1 und f2 nach dieser Formalisierung "ungefahr proportional\ sind, heien sie asymptotisch
aquivalent.
Notation: f1 f2.
Die konstante Funktion mit Wert c wird ebenfalls
mit c bezeichnet.
Modellannahmen:
Die Laufzeit jedes Codestucks, in dem keine Schleife
und kein Methodenaufruf vorkommen, ist 1.
Die Laufzeit einer Schleife setzt sich additiv zusammen aus
{ Laufzeit fur die Auswertung der Fortsetzungsbedingung,
{ Laufzeit fur den Rumpf der Schleife und
{ Laufzeit fur die interne, unsichtbare Organisation
der Schleife selbst.
{ Speziell bei for{Schleife: Zusatzlich Aufwand fur
den Intialisierungsteil und die Fortschaltung.
Beobachtung: f ist beschrankt und uberall strikt
positiv () f 1.
f
for ( int i = 0; i < n; i++ )
Initialisierung
Informatik II { Sommersemester 1999
165
Informatik II { Sommersemester 1999
Fortschaltung
166
Diskussion:
Fortsetzung Modellannahmen:
Die Gesamtlaufzeit fur die interne Organisation ei-
Diese Modellannahmen sind sicher eine Vereinfa-
ner Schleife ist asymptotisch aquivalent zur Anzahl
Durchlaufe.
Die Laufzeit eines Methodenaufrufs setzt sich addi-
tiv zusammen aus
{ Laufzeit fur den Inhalt der Methode und
{ Laufzeit fur die interne, unsichtbare Organisation
des Methodenaufrufs selbst.
Die Laufzeit fur die interne Organisation eines Methodenaufrufs ist 1.
Informatik II { Sommersemester 1999
Fortsetzungsbedingung
167
chung der Realitat,
aber immer noch ausreichend nahe an der Realitat
dran fur aussagekraftige Analysen.
Wenn die Laufzeiten zweier Algorithmen nicht asymptotisch aquivalent sind, kann man sofort entscheiden, welcher der beiden besser ist im Falle, da die
Kenngroen "ins Unendliche wachsen\.
Nur bei asymptotischer A quivalenz mu man noch
genauere Vergleiche anstellen.
Erinnerung: Wenn Algorithmus A "im Unendlichen\
besser ist als Algorithmus B , kann B bei kleinen
Werten der Kenngroen dennoch besser als A sein.
Beachte: Bei komplizierteren Algorithmen kann es
sein, da die Kenngroen schon recht gro werden
mussen, bevor sich der asymptotische Vorteil von A
auszuwirken beginnt.
Informatik II { Sommersemester 1999
168
Ziel: Wir wurden "\ gerne so denieren, da f1 f2
immer noch gilt, wenn f1 und f2
Technische Unschonheit:
c2 . f1
endlich viele Nullstellen haben,
ansonsten aber die Bedingung fur asymptotische
f1
A quivalenz erfullen.
f2
1 .
f
c1 1
Losung: f1 f2 soll von jetzt an schon gelten, wenn
nur
f1(n1; : : : ; nk) c1 f2(n1; : : : ; nk) und
f2(n1; : : : ; nk) c2 f1(n1; : : : ; nk)
fur n1 N1; : : : ; nk Nk mit beliebigen, aber festen
Werten N1; : : : ; Nk 2 N gelten.
Erlauterung:
Durch die Nullstellen von f2 gilt nicht mehr f1 f2
(kein c1 > 0 moglich).
Aber "ins Unendliche\ gilt f1 f2 irgendwie doch.
Informatik II { Sommersemester 1999
169
Informatik II { Sommersemester 1999
170
Entscheidend fur guten Durchblick:
Fundamentale Einsicht dazu:
Das heit hier:
Seien n; k 2 N fest.
Seien f1; f2; : : : ; fn beliebige Funktionen
N k ;! N .
Seien F1(x) := maxff1(x); f2(x); : : : ; fn(x)g und
F2(x) := f1(x) + f2(x) + + fn(x) fur x 2 N k .
Reduktion auf das Wesentliche.
Die Gesamtlaufzeit eines Algorithmus setzt sich additiv aus den Laufzeiten der einzelnen Teile zusammen.
Nur die asymptotisch am schnellsten wachsenden
Teile zahlen.
Informatik II { Sommersemester 1999
Dann gilt F1 F2 mit c1 = 1 und c2 = n.
Denn: Fur x 2 N k gilt
maxff1(x); f2(x); : : : ; fn(x)g
1 (f1(x) + f2(x) + + fn(x)) und
f1(x) + f2(x) + + fn(x)
n maxff1(x); f2(x); : : : ; fn(x)g.
171
Informatik II { Sommersemester 1999
172
Denition: Seien f1 und f2 Funktionen
Nk
Erinnerung von zwei Folien fruher:
f1 + + fn maxff1; : : : ; fng.
Konsequenz: Seien f1; : : : ; fn Funktionen
N k ;! N , so da f2; : : : ; fn 2 O(f1).
;! Dann gilt (f1 + + fn) f1.
;! N , so da
es ein c1 > 0 und N1 2 N mit
f1(n) c1 f2(n) fur n N1 gibt,
aber kein c2 > 0 und N2 2 N mit
f2(n) c2 f1(n) fur n N2.
Dann heit f1 durch f2 dominiert.
Beachte: Diese Konsequenz ist die formale Konkreti-
Notation: Fur eine Funktion f : N k ;! N ist
(f ) die Menge aller zu f asymptotisch aquivalen-
Beweis dieser Konsequenz:
ten Funktionen,
o(f ) die Menge aller von f dominierten Funktionen
und
O(f ) = (f ) [ o(f ).
sierung von "nur die am schnellsten wachsenden Teile
zahlen\.
Nachste zwei Folien.
Annahme rein zur notationellen Vereinfachung in der
Formulierung des Beweises: f1(x) 6= 0 fur alle x 2 N k .
;! Allgemein ublicher Terminus "O{Notation\.
Informatik II { Sommersemester 1999
173
Zu zeigen: Es gibt c1; c2 > 0, so da fur alle x 2 N k
gilt:
174
Bleibt noch zu zeigen: c2 < +1.
Begrundung fur c2 < +1:
f1(x) c1 (f1(x) + + fn(x)) und
(f1(x) + + fn(x)) c2 f1(x).
Erinnerung: Voraussetzung war
f2; : : : ; fn 2 O(f1).
Mit anderen Worten: Es gibt d2; : : : ; dn > 0 mit
fi(x) < di f1(x) fur x 2 N k und i 2 f2; : : : ; ng.
Konstruktion von c1 und c2:
c1 := 1 tut's oensichtlich.
Nun c2:
c2 f1(x) (f1(x) + + fn(x))
() c2 1 + ff2((xx)) + + ffn((xx))
1
1
Also: Setze
Informatik II { Sommersemester 1999
;! Fur alle x 2 N k gilt
f2(x) + + fn(x) d + + d < +1
2
n
f1(x)
f1(x)
Insbesondere schluendlich:
Informatik II { Sommersemester 1999
c2 = maxk 1 + ff2((xx)) + + ffn((xx)) < +1
x2N
1
1
c2 := maxk 1 + ff2((xx)) + + ffn((xx)) > 0
x2N
1
1
175
Informatik II { Sommersemester 1999
176
Gesamtlaufzeit gema Modellannahmen
= 1{mal beschrankte Laufzeit fur "int sum=0\
+ 1{mal beschrankte Laufzeit fur den Initialisierungs-
Einfaches, kunstliches Beispiel:
int sum = 0;
for ( int i = 0; i < m; i++ )
{
int k = i * i;
for ( int j = 0; j < n; j++ )
sum += k * j;
}
+
+
+
+
+
+
+
Informatik II { Sommersemester 1999
177
Zusammenfassung: Die Gesamtlaufzeit jedes dieser
neun Summanden ist
teil der aueren Schleife
m{mal beschrankte Laufzeit fur Fortsetzungsbedingung und Fortschaltung in der aueren Schleife
1{mal Laufzeit fur die interne Organisation der
aueren Schleife ( m)
m{mal beschrankte Laufzeit fur "int k=i*i\
m{mal beschrankte Laufzeit fur den Initialisierungsteil der inneren Schleife
m n{mal beschrankte Laufzeit fur Fortsetzungsbedingung und Fortschaltung in der inneren Schleife
m{mal Laufzeit fur die Organisation der inneren
Schleife (jeweils n)
(m n){mal beschrankte Laufzeit fur "sum+=k*j\.
Informatik II { Sommersemester 1999
178
A hnliches Beispiel: Selection{Sort
Erinnerung:
int indexOfMin (Object[] A, int first_index,
Comparator cmp)
{
int index = first_index;
for ( int i=first_index+1; i<A.length; i++ )
if ( cmp.is_less_than ( A[i], A[index] ) )
index = i;
return index;
}
1 oder
m oder
m n.
void swapComponents (Object[] A,
int index1, int index2)
{
Object x = A[index1];
A[index1] = A[index2];
A[index2] = x;
}
"Nur die am schnellsten wachsenden Teil zahlen\
;! Gesamtlaufzeit des Beispiels ist m n.
void sort (Object[] A, Comparator cmp)
{
for ( int i=0; i<A.length; i++ )
{
int index = indexOfMin (A, i, cmp);
swapComponents (A[i], A[index]);
}
}
Informatik II { Sommersemester 1999
179
Informatik II { Sommersemester 1999
180
Komplexeres Beispiel: Mergesort mit beliebiger Eingabelange (vgl. Vorlesungsthema 5)
"Erbsenzahlen\ fur Selection{Sort:
Sei n := A.length.
Laufzeit fur die Abarbeitung von indexOfMin ist
n ; i + 1 im i{ten Durchlauf durch die Schleife
in sort.
Laufzeit fur eine Abarbeitung von swapComponents
ist immer 1.
;! Laufzeit fur den i{ten Durchlauf durch
die Schleife in sort ist n ; i + 1.
;! Gesamtlaufzeit ist
n
X
i=1
(n ; i + 1) =
n
X
i=1
21 17 41 67 41 12 15 23 88 9 27
21 17
17 21
41 67 41 12 15
41 67
12 41
17 21 41 67
i = n(n2+ 1) n2
23 88
15 23
12 15 23 41
12 15 17 21 23 41 41 67
9
9 88
27
27
9 27 88
9 27 88
9 12 15 17 21 23 27 41 41 67 88
Informatik II { Sommersemester 1999
181
Iterative Implementation:
182
Laufzeit des Algorithmus
Vorbetrachtung: Anzahl der Durchlaufe durch die
auere Schleife bestimmen.
public void sort ( Object[] A, Comparator cmp )
{
for ( int k = 1; k < n; k *= 2 )
for ( int j = 0; j < n+k; j += 2*k )
{
int first = j;
int middle = j + k - 1;
int last
= j + 2*k - 1;
if ( n < last )
last = n;
merge ( A, cmp, first, middle, last );
}
}
Erinnerung: Ist die Anzahl der Elemente eine Zweierpotenz 2k , dann werden zum Sortieren k Schleifendurchlaufe benotigt.
Anders herum formuliert: k = log2 n Schleifendurchlaufe fur n = 2k Elemente.
Erinnerung aus Thema 6 der Vorlesung:
Aufruf merge(A,cmp,first,middle,last)
erwartet, da A[first]..A[middle] und
A[middle+1]..A[last] in sich sortiert sind, und
sorgt dafur, da A[first]..A[last] in sich sortiert ist.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
183
Beobachtung: Fur beliebiges n sei N = 2k die kleinste
Zweierpotenz n.
;! Die Anzahl der Schleifendurchlaufe fur n
Elemente ist k = log2 N = dlog2 ne.
Fehlt noch: Laufzeit pro Durchlauf durch die auere
Schleife.
Informatik II { Sommersemester 1999
184
Laufzeit pro Durchlauf der aueren Schleife:
Erinnerung:
Zum Zusammenfugen zweier in sich sortierter Teilse-
public void sort ( Object[] A, Comparator cmp )
{
for ( int k = 1; k < n; k *= 2 )
for ( int j = 0; j < n+k; j += 2*k )
{
int first = j;
int middle = j + k - 1;
int last
= j + 2*k - 1;
if ( n < last )
last = n;
merge ( A, cmp, first, middle, last );
}
}
quenzen zu einer neuen werden beide Teilsequenzen
insgesamt einmal durchlaufen.
j1
17 21 41 67
In einem Schleifendurchlauf werden paarweise disjunkte Teilsequenzen durchlaufen.
185
;! Gesamtlaufzeit fur alle Aufrufe von
in einem Durchlauf der aueren
Schleife ist ebenfalls n.
merge
;! Gesamtlaufzeit des Algorithmus ist
n dlog2 ne.
Informatik II { Sommersemester 1999
186
Rechnen mit der O{Notation
Merke:
Erinnerung:
Fur feste n; k 2 N deniert die Asymptotik
eine partielle Ordnung auf den Funktionen
N k ;! N .
Damit konnen die Laufzeiten zweier Algorithmen miteinander verglichen oder die Laufzeit
eines Algorithmus durch eine Funktion ausgedruckt werden.
Bei asymptotischen Betrachtungen von Funktionen mussen nur die "am schnellsten wachsenden\ Summanden betrachtet werden.
Falls c1; c2 > 0 und n0 2 N existieren mit f1(n) c1f2(n) und f2(n) c2f1(n) fur n n0, schreiben
wir f1 2 (f2) (und umgekehrt: f2 2 (f1)).
Falls nur c1, aber nicht c2 existiert: f1 2 o(f2).
O(f2) = (f2) [ o(f2)
;! f1 2 O(f2) bedeutet gerade, da es
ein c1 mit f1 c1 f2 gibt (egal ob es
umgekehrt ein c2 gibt oder nicht).
Auch bei komplizierten Algorithmen kommt
Sinngema alles ubertragbar auf den Fall mehrerer
man daher im allgemeinen zu vergleichsweise
einfach strukturierten Funktionen.
Informatik II { Sommersemester 1999
i
12 15 17 21
Konsequenz: Aufruf von merge ist asymptotisch
aquivalent zur Lange des Endergebnisses.
Laufzeit pro Durchlauf auerhalb merge: oensichtlich
n.
Frage: Was ist mit merge selbst?
Informatik II { Sommersemester 1999
j2
12 15 23 41
Kenngroen.
187
Informatik II { Sommersemester 1999
188
Weitere Beobachtung: Wenn es fur f : N ;! R
ein n0 2 N mit f (n) 1 fur n n0 gibt, dann gilt
bf c df e.
Beobachtung:
Erinnerung Logarithmengesetz: Fur a; b > 1 gilt
loga n = log b
a
logb n
Seien fa; fb : N n f0g ;! N mit
{ fa(n) = dloga ne und
{ fb(n) = dlogb ne.
Begrundung:
Nur die Existenz von c > 0 und N0 2 N zu zeigen,
so da df (n)e c bf (n)c fur n N0 gilt.
Losung: c := 2.
Insbesondere: blog nc dlog ne.
Also: Es gilt fa dloga be fb und
fb dlogb ae fa.
;! fa fb.
;! Basis a > 1 des Logarithmus braucht bei
Somit Rechtfertigung fur weitere Vereinfachung der
Schreibweise:
(log n) statt (dlog ne),
O(log n) statt O(dlog ne),
etc.
asymptotischen Betrachtungen nicht angegeben zu werden: dloga ne ;! dlog ne.
Informatik II { Sommersemester 1999
189
Oensichtliche Transitivitaten:
190
Generelle Limes{Regel (ohne Beweis):
Wenn f2 : N ;! N nur endlich viele Nullstellen hat,
dann gilt
Wenn f1 2 O(f2) und f2 2 O(f3), dann
auch f1 2 O(f3).
Wenn f1 2 o(f2) und f2 2 o(f3), dann
auch f1 2 o(f3).
f1 2 o(f2) () n;!1
lim ff1((nn)) = 0
2
Nutzlich in diesem Zusammenhang:
Regel von l'H^opital
Wenn f1 2 O(f2) und f2 2 o(f3) oder
f1 2 o(f2) und f2 2 O(f3), dann auch
f1 2 o(f3).
Salopp formuliert:
f (x) = lim f 0(x)
lim
x;!1 g0(x)
x;!1 g(x)
Wenn f1 2 (f2) und f2 2 (f3), dann
auch f1 2 (f3).
00
000
= x;!1
lim fg00((xx)) = x;!1
lim fg000((xx)) = Wenn f1 2 O(f2) und f2 2 (f3) oder
f1 2 (f2) und f2 2 O(f3), dann auch
f1 2 O(f3).
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
191
Informatik II { Sommersemester 1999
192
Vergleich von Potenzfunktionen:
Seien k; ` 2 N mit k < `.
k
lim n`1;k = 0
;! n;!1
lim nn` = n;!1
Beispielanwendung der Regel von l'H^opital:
lim 1=x
lim logxe x = x;!1
1 =0
x;!1
;! dlog ne 2 o(n)
;! n dlog ne 2 o(n2)
Konsequenz aus der generellen Limes{Regel:
nk 2 o(n`)
;! Mergesort ist tatsachlich um Groenord-
Anwendung auf Schnittmengenalgorithmus
(Vorlesungsthema 5):
Der "schnelle\ Algorithmus hat im Worst und Best
Case Laufzeit (jAj + jB j).
Worst Case fur den "naiven\ Algorithmus: tritt auf
im Falle A B .
;! Im Fall jAj jB j ist der Unterschied
wieder um Groenordnungen:
(jAj) ! (jAj2)
nungen schneller als Selection{Sort.
Informatik II { Sommersemester 1999
193
194
Exkurs:
Exponentielle Laufzeit
Bedeutet: Es gibt ein a > 1, so da die Laufzeit
an ist.
Beispiel: Fur a 2 N ; a > 1 ist das die Mindestlaufzeit des "primitiven\ Algorithmus fur jedes Problem
aus n sukzessiven Entscheidungen mit a Alternativen.
Das heit:
{ Das Problem besteht darin, n Entscheidungen zu
treen.
{ Fur jede Entscheidung stehen a Alternativen zur
Auswahl.
{ "Primitiver\ Algorithmus: Alle an Kombinationen
von Entscheidungen werden durchlaufen, um die
beste zu nden.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
195
Fur viele konkrete Entscheidungsprobleme nach die-
sem Muster gibt es bessere als exponentielle Algorithmen.
Es gibt aber auch Entscheidungsprobleme, fur die
kein Algorithmus bekannt ist, der im Worst Case
weniger als exponentielle Laufzeit hat.
Fur eine ganze Klasse solcher Probleme (NP {
schwere Probleme) legen Ergebnisse aus der Vorlesung Theoretische Informatik nahe, da die Laufzeit
im Worst Case grundsatzlich mindestens exponentiell ist.
Beispiel:
{ Gegeben ein Lieferwagen und n Stucke zum
Transportieren, wie kann moglichst viel mit einer Fuhre mitkommen.
{ Entscheidungen: Fur jedes Stuck, ob es mitkommt oder nicht (also a = 2).
Informatik II { Sommersemester 1999
196
Vergleich zweier Exponentialfunktionen
wieder mit der generellen Limes{Regel:
Sei 1 < a < b.
Merke:
O(), o() und () sind transitiv.
o() "schlagt\ dabei O(),
und O() "schlagt\ ().
x
x
lim ab = 0
;! x;!1
lim abx = x;!1
;! ax 2 o(bx)
Alle Logarithmusfunktionen sind asympto-
Vergleich Potenz-/Exponentialfunktion
mit der Regel von l'H^opital:
k ;1
k
k ;2
lim x = lim k x
= lim k (k ; 1) x
x;!1 ax x;!1 log a ax x;!1 (log a)2 ax
e
e
= = x;!1
lim (log ak)! k ax = 0
e
tisch zueinander aquivalent.
Jede Potenzfunktion wachst schneller als jede
Logarithmusfunktion.
Jede Exponentialfunktion wachst schneller als
jede Potenzfunktion.
Potenzfunktionen (bzw. Exponentialfunktionen) sind untereinander grundsatzlich nicht
asymptotisch aquivalent.
;! nk 2 o(an)
Informatik II { Sommersemester 1999
197
Konkrete Zahlen:
n
n2
n3
n4
2n
3n
3
1
1
1
1
2
2
4
8
16
4
9
3
9
27
81
8
27
4
16
64
256
16
81
5
25
125
625
32
243
...
...
...
...
...
...
10
100
1.000
10.000
1.024
59.049
...
...
...
...
...
...
20
400
8.000
160.000
...
...
100
10.000
...
10
6
...
8
10
6
10
...
30
10
3,510
Informatik II { Sommersemester 1999
198
Fakultatsfunktion n! = 1 2 3 (n ; 1) n
Beobachtung: Die Anzahl von Permutationen einer
n{elementigen Menge ist n!.
;! Sortieren durch systematisches Auspro-
bieren aller Permutationen, bis eine Permutation in Sortierreihenfolge gefunden
ist, wurde Laufzeit proportional n! oder
noch schlechter erfordern.
9
...
47
510
Beachte auch: Verbesserung der Computerpower um
z.B Faktor 10 erlaubt
p
bei nk um Faktor k 10 groere Eingaben in dersel-
Frage: Wie schlecht ist Laufzeit (n!)?
ben Zeit zu losen,
aber bei an konnen die Eingaben nur um den Summanden loga(10) groer werden:
am = 10 an () m ; n = loga(10)
Informatik II { Sommersemester 1999
199
Informatik II { Sommersemester 1999
200
A hnliches Beispiel:
Traveling{Salesperson Problem (TSP)
Gegeben: n Punkte in der Ebene.
Gesucht: Kurzeste geschlossene Rundtour startend
(und endend) mit p1.
p10
p5
p4
p1
p14
p16
p9
p11
p2
p7
p3
p6
zeigen, denn:
Fur " > 0 mit " < a ; 1 wurde dann ebenfalls
n! 2 O((a ; ")n) gelten.
Wegen (a ; ")n 2 o(an) und Transitivitat wurde
somit n! 2 o(an) gelten.
Beweisidee zu an 2 O(n!):
p8
Beliebig, aber fest gegeben: a > 1.
Gesucht: na 2 N und ca > 0, so da
n! ca an fur n na ist.
p13
p15
p12
Vermutung: n! wachst so schnell, da sogar an 2
o(n!) fur alle a > 1 gilt.
Beobachtung: Es reicht an 2 O(n!) fur alle a > 1 zu
Anzahl Rundtouren: (n ; 1)!
Frage: Wie schlecht ist systematisches
Beweis: Nachste zwei Folien.
Ausprobieren hier also mindestens?
Informatik II { Sommersemester 1999
201
Ansatz: Logarithmisierung und Anwendung der Logarithmengesetze
n! ca an () log2
()
n
X
i=1
n !
Y
i=1
i log2 (ca an)
() ; log2 (ca) n log2(a) ;
() log2 c1 a
n
X
i=1
i=1
i=1
1
log2 c da () c1 2da
a
a
() ca 21da
log2(i)
Konsequenz: Mit na := dae und ca :=
gewunscht n! ca an fur alle n na.
(log2(a) ; log2(i))
Fur n dae ist der rechte Ausdruck
dae
X
202
Wichtig: da ist eine Konstante und damit
insbesondere unabhangig von n.
Auswertung:
log2(i) log2(ca) + n log2(a)
n
X
Informatik II { Sommersemester 1999
1
2da
gilt wie
;! Beweis fertig.
(log2(a) ; log2(i)) =: da
Informatik II { Sommersemester 1999
203
Informatik II { Sommersemester 1999
204
Fibonacci{Reihe
Genauere Asymptotik von fib: Durch Anwendung
der "Schullosung\ fur quadratische Gleichungen
r
Einkreisung: "fib\ wachst ...
... hochstens so schnell wie 2n:
Falls fib(k) c 2k fur alle k
auch
< n ist, dann gilt
fib(n) = fib(n ; 1) + fib(n ; 2)
c (2n;1 + 2n;2) = c 2n;2 3 c 2n :
p
... mindestens so schnell
p k wie ( 2)n:
Falls fib(k) c ( 2) fur alle k < n ist, dann gilt
auch
fib(n) = fib(n ; 1) + fib(n ; 2)
p
p
c ( 2)n;1 + ( 2)n;2
p p
= c ( 2)n;2 2 + 1
p
p
c ( 2)n;2 2 = c ( 2)n :
Informatik II { Sommersemester 1999
Idee: Gesucht ist a > 1 mit
an = an;1 + an;2
() a2 = a + 1
() a2 ; a ; 1 = 0
r
() a = 21 14 + 1
Resultat: "fib\ ist asymptotisch aquivalent zu
p !n
1+ 5
2
205
(1; 618)n
Informatik II { Sommersemester 1999
206
Thema 9: Asymptotik und Kodierungslange
Merke:
Fallbeispiel: Wie so oft Sortieren
Algorithmen mit exponentieller Laufzeit sind
im Grunde "jenseits von gut und bose\.
Exponentielle Laufzeit wachst sogar so
schnell, da multiplikative Verbesserungen der
Rechenpower sich nur noch additiv auf die
Groe der Eingaben, die in fester Zeit bearbeitet werden konnen, auswirken.
Die Fibonacci{Reihe wachst so schnell wie
eine Exponentialfunktion mit Basis 1; 618.
Die Fakultatsfunktion wachst sogar noch
schneller als alle Exponentialfunktionen.
Informatik II { Sommersemester 1999
2
x2 + px + q = 0 () x = ; p2 p4 ; q
Erinnerung: Bisheriger "Rekord\ ist (n log n).
Aber: Dieses Resultat beruhte auf stillschweigenden Voraussetzungen.
Konkret: Die Operationen auf dem Datentyp der
zu sortierenden Elemente wurden implizit als (1)
angenommen.
Welche Operationen sind das:
{ Zuweisung einer Variable zu einer anderen,
{ Vergleich zweier Variablen.
207
Informatik II { Sommersemester 1999
208
Zuweisung: Kann in Java grundsatzlich als (1) an-
genommen werden (nur Referenz kopiert bei Klassentypen).
Also zu betrachten:
Beispiele:
java.lang.BigNumber
Zahlen.
fur beliebig groe ganze
Datentyp String zu sortieren nach Telefonbuchord-
Vergleich zweier Elemente
nung (lexikographisch).
In vielen Anwendungsfallen des Sortierproblems
reicht ein groenbeschrankter Datentyp wie int
oder double aus, um auch die allergroten auftretenden Zahlen zu kodieren.
;! Annahme (1) Laufzeit pro Vergleich
entspricht der empirischen Beobachtung der "Wachstumskurve\.
Ansonsten fuhrt die Annahme (1) aber zu einer systematischen Unterschatzung der empirischen
"Wachstumskurve\!
Lexikographisch zwei Strings S1 und S2
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
209
Algorithmus fur lexikographischen
Zeichen.
210
Lexikographischer Vergleich zweier Strings ist im
allgemeinen nicht in O(1) Laufzeit moglich,
sondern kann proportional zur Maximallange k0 der
public class LexStringComparator implements Comparator
{
public boolean isLessThan ( Object o1, Object o2 )
{
String str1 = (String)o1;
String str2 = (String)o2;
Strings werden.
Konsequenz:
(n log n) als Gesamtlaufzeit fur Mergesort ist hier
for ( int i = 0; ; i++ )
if ( i == str2.length )
return false;
else if ( i == str1.length )
return true;
else if ( str1[i] < str2[i] )
return true;
else if ( str1[i] > str2[i] )
return false;
nicht korrekt,
sondern im Worst Case (k0 n log n).
Problem: Wenn sich die Strings im wesentlichen nur
}
}
Invariante: Falls der Algorithmus bis zum Ende des i{ten Durchlaufs nicht abgebrochen wur-
de, gilt str1.length>=i, str2.length>=i sowie
str1[j]==str2[j] f
ur alle
0
1 am
Informatik II { Sommersemester 1999
Falls S1 ein Prax von S2 ist: S1 < S2.
Falls S1 = S2 oder S2 ein Prax von S1 ist: S1 6< S2.
Ansonsten entscheidet das erste ungleiche
Beobachtung:
Stringvergleich:
Ende des i{ten Durchlaufs.
vergleichen:
j 2 f ;:::;i ; g
211
in den letzten Zeichen unterscheiden, mu jeder String
mindestens einmal durchlaufen werden.
;! Es geht im Worst Case grundsatzlich
nicht asymptotisch schneller als (K ),
K Summe aller Stringlangen.
Frage: Geht es in (K ) Laufzeit?
Informatik II { Sommersemester 1999
212
Antwort: Es geht in (K ) Laufzeit mit
Idee fur Umsetzung:
einem Algorithmus namens Bucketsort.
Ideen:
Sei k0 weiterhin die maximale Lange unter den zu
sortierenden Strings.
Die einzelnen Strings kommen gema ihrer Lange
erst nach und nach "ins Spiel\.
Schleifeninvarianten: Nach i Durchlaufen sind
{ alle Strings mit Lange k0 ; i + 1 im Spiel und
{ untereinander nach den Zeichen mit den Indizes
k0 ; i + 1; k0 ; i + 2; ::: lexikographisch sortiert.
Konsequenz: Nach k0 Durchlaufen sind alle Strings
im Spiel und lexikographisch untereinander sortiert.
Informatik II { Sommersemester 1999
213
Beispiel:
Ein "Korbchen\ (Bucket) fur jeden Buchstaben des
Alphabets.
Im Durchlauf Nr. i wird jeder String str, der mindestens k0 ; i + 1 Zeichen hat, in das Bucket fur
Zeichen str[k0 ; i + 1] gesteckt.
Die Strings mit mehr als k0 ; i + 1 Zeichen werden
in der Reihenfolge ihrer bisherigen Sortierung auf
die Buckets verteilt.
;! Unter Strings mit gleichem Zeichen am
Index k0 ;i+1 wird die Reihenfolge aus
den vorhergehenden Runden bewahrt.
Die neuen Strings (also die mit genau k0 ; i + 1
Zeichen) werden schon vor den langeren Strings auf
die Buckets verteilt.
;! Praxe werden richtig eingeordnet.
Informatik II { Sommersemester 1999
214
1. Runde:
String
Lange
Antonio
7
Thomas
6
Andrea
6
Sabine
6
7
Eusebia
Anton
5
Gerda
5
Tobias
6
7
Antonia
7
Andreas
Ibrahim
7
a
Eusebia
Antonia
b
c
m
n
o
Ibrahim
s
Andreas
Antonio
z
Informatik II { Sommersemester 1999
215
Informatik II { Sommersemester 1999
216
2. Runde:
a
e
i
s
3. Runde:
Andrea
a
Andreas
b
Gerda Thomas
Eusebia
e
Andrea
h
Ibrahim
n
Anton
Tobias
Sabine
Eusebia
Antonia
Thomas
Ibrahim
Andreas
Antonio
Tobias
Sabine
Antonia
Antonio
z
z
Informatik II { Sommersemester 1999
4. Runde:
a
217
Gerda
Eusebia
i
Tobias
m
n
o
5. Runde:
Ibrahim
d
e
Informatik II { Sommersemester 1999
Sabine
a
b
c
Tobias
d
Andrea
o
Thomas
Sabine
Andreas
Thomas
Anton
Antonia
r
s
Antonio
t
r
218
Andrea
Ibrahim
Gerda
Eusebia
Anton Antonia
Antonio
Andreas
z
z
Informatik II { Sommersemester 1999
219
Informatik II { Sommersemester 1999
220
6. Runde:
7. Runde:
a
Sabine
b
Ibrahim
e
Gerda
h
n
o
u
Thomas
Andrea
Tobias
Andreas
Anton
Antonia
a
Andrea
e
Eusebia
f
g
Gerda
h
i
Ibrahim
s
Sabine
t
Thomas
Andreas
Anton
Antonia
Antonio
Antonio
Eusebia
Tobias
z
z
Informatik II { Sommersemester 1999
221
Implementation von Bucketsort in Java:
se java.util.Vector ist im Prinzip ein Array,
bei dem Elemente eingefugt und geloscht werden
konnen.
Jeder Bucket kann als ein Vector{Objekt realisiert
werden.
Die Buckets bilden also einen Array vom Typ
mit 26 Elementen.
Arrayindex fur das Zeichen, das in der char{Variable
c
gespeichert ist:
(int)(Character.toLowerCase(c)-'a')
Informatik II { Sommersemester 1999
222
Fortsetzung Implementation von Bucketsort in Java
Erinnerung: Ein Objekt der vordenierten Klas-
Vector[]
Informatik II { Sommersemester 1999
Alle Strings werden vor der ersten "Runde\ des Kernalgorithmus durch einen Durchlauf von Bucketsort
mit Buckets 1; : : : ; k0 nach Lange sortiert:
1
2
3
4
5
6
7
Anton
Thomas
Antonio
Gerda
Andrea
Eusebia
Sabine Tobias
Antonia Andreas
Ibrahim
Nach jeder "Runde\ des Kernalgorithmus werden
die einzelnen Buckets "von 'a' bis 'z'\ in einen
separaten Vector A kopiert und von dort in der
nachsten Runde wieder verteilt.
223
Informatik II { Sommersemester 1999
224
Asymptotische Laufzeit von Bucketsort:
Intuition zur letzten Gleichung:
Vorab die n Strings nach ihrer Lange sortieren:
2 O(n + k0 + K ) = O(K ).
i =
n i=
Sei ni die Anzahl der Strings mit
mindestens i Zeichen.
Aufwand fur Runde Nr. i: 2 (n k ;i ).
;! Gesamtaufwand fur alle Runden:
( 0
+1)
0k
1 0k 1
X
X
2 @ n k ;i A = @ niA = (K ) :
0
i=1
0
( 0
+1)
225
7
5
A n t o n
T h o m a
i
s
o
A n d r
S a b i
a
e
i
e
n
E u
s
e b
A n
G e
t
r
o
d
a
n
a
s
A n d
r
e a
o
s
I
a
h
m
b r
i
i
Informatik II { Sommersemester 1999
226
Thema 10: Untere asymptotische Schranken
Merke:
Erinnerung:
Bei der Berechnung der asymptotischen Lauf-
Mergesort lost das generische Sortierproblem in
(n log n T ) Zeit (T der durchschnittliche Auf-
zeit eines generischen Algorithmus (z.B. Sortieralgorithmen wie Mergesort) mu immer
mitberucksichtigt werden, da die Basisoperationen auf unterschiedlichen Datentypen unterschiedliche asymptotische Laufzeit haben
konnen.
Fur den wichtigen Spezialfall des allgemeinen Sortierproblems, da Strings lexikographisch zu sortieren sind, erreicht Bucketsort
im Gegensatz zu Mergesort optimale asymptotische Laufzeit im Worst Case (namlich
asymptotisch aquivalent zur Gesamtsumme
aller Stringlangen).
Informatik II { Sommersemester 1999
6
9
T o b i a
A n t o n
i=1
Informatik II { Sommersemester 1999
1 2 3 4 5
11 11 11 11 11
wand pro Vergleichsoperation).
Bucketsort ist mit (K ) asymptotisch optimal fur
die lexikographische Sortierung von Strings.
Beobachtung: Mit Bucketsort lassen sich z.B. auch
ganze Zahlen sortieren: als "Strings\ von Ziern.
Interessante Fragen:
Ist (n log n T ) allgemein das letzte Wort?
Kann man diesen "Rekord\ mit Bucketsort zumin-
dest fur gewisse Datentypen und Sortierordnungen
unterbieten?
227
Informatik II { Sommersemester 1999
228
Grundsatzliche Grenze: Um n unterschiedliche Werte
eines beliebigen Datentyps als Strings mit k verschiedenen Zeichen zu kodieren, werden mindestens blogk nc
Zeichen pro String im Durchschnitt benotigt.
;! In Bitdarstellung also mindestens blog2 nc.
Idee zum Beweis der grundsatzlichen Grenze: Alle
Strings lassen sich zusammen zu einem Digitalbaum
mit n Endknoten "%\ verschmelzen.
Beispiel aus der Behandlung von Bucketsort:
Konsequenzen: aus dieser grundsatzlichen Grenze:
Besser als (n log n) kann Bucketsort im Worst
Case selbst bei optimaler Kodierung der zu sortierenden Daten nicht werden.
Auch kein anderer Algorithmus, weil im Worst Case
sicher alle (n log n) Bits mindestens einmal angeschaut werden mussen.
Aber immerhin: Mergesort konnte bei lexikographischer Sortierung von Strings nicht einmal besser als
(n log2 n) werden.
Informatik II { Sommersemester 1999
229
A
E
G
I
S
n
u
e
b
a
s
r
r
b
o
b
o
e
d
a
i
m
i
n
b
a
h
n
a
a
i
%
i
e
s
s
%
%
t
d
r
e
a
s
%
i
%
%
a
o
a
m
%
%
%
%
T
h
Informatik II { Sommersemester 1999
o
%
230
Beispiel zur hilfreichen Beobachtung (k = 2):
Grundsatzliche Grenze folgt nun aus folgender
Hilfsbehauptung: Bei einem Baum mit n Endknoten
(Blattern) und maximal k Nachfolgern pro Knoten ist
die durchschnittliche Hohe aller Endknoten mindestens
blogk nc.
Hilfreiche Beobachtung: Durch Balancierung des
Baumes kann die durchschnittliche Hohe der Endknoten nur besser werden.
Informatik II { Sommersemester 1999
231
!
Informatik II { Sommersemester 1999
232
Weiter: in einem optimal balancierten Baum mit m =
k` Endknoten hat jeder Endknoten Hohe ` = logk(m).
Zusammenfassung: Wegen (log n) oder mehr pro
Vergleich ist nichts Besseres als (n log n) beim Sortieren im Worst Case drin.
Anschlufrage: Kann unter der idealisierten Annahme, da ein Vergleich zweier Elemente nur (1) Zeit
kostet, besser als in (n log n) Laufzeit sortiert werden?
;! In einem optimal balancierten Baum mit m Endknoten, k`;1 < m k`, hat jeder Endknoten
Hohe ` ; 1 = blogk (m)c oder ` = dlogk (m)e:
Methodisches Problem:
Die Anschlufrage bezieht sich nicht auf einen kon-
kreten Algorithmus,
sondern auf die (unendlich groe!) Menge aller uberhaupt nur denkbaren Sortieralgorithmen.
Kann man daruber uberhaupt irgendwelche Aussagen treen?
;! Hilfsbehauptung bewiesen.
Informatik II { Sommersemester 1999
233
Konkretisierung der Fragestellung:
Erinnerung: Im generischen Sortierproblem (Vorle-
sungsthema 2) war nichts uber den Elementtyp bekannt abgesehen von der Vergleichsoperation "\.
Dies scheint auch der einzige gemeinsame Nenner
aller moglichen Denitionen von Datentyp und "\
zu sein.
Ein wahrhaft generischer Sortieralgorithmus hat also
keine Information uber die zu sortierenden Elemente abgesehen von der Antwort true/false durch
Anwendung von "\ auf Paare von Elementen.
Und das auch nur als "Black Box\, d.h. ohne Einsicht in das Wesen von "\
Im Gegensatz etwa zur Ausnutzung des Wesens von
lexikographischer Reihenfolge im nichtgenerischen
Algorithmus Bucketsort.
Konkretisierte Frage: Kann ein Algorithmus, der nur
Informatik II { Sommersemester 1999
234
Antwort: Wenn Datentyp T unendlich gro ist, ist im
Worst Case nichts Besseres als (n log n) moglich.
Beweisidee:
Seien a1; : : : ; an 2 T paarweise verschieden mit
a1 a2 an.
Fur jede Permutation (a(1); : : : ; a(n)) von
(a1; : : : ; an) als Eingabe durchlauft der Algorithmus eine charakteristische Folge von Anwendungen
von "\.
Fur je zwei Permutationen mussen diese Folgen
irgendwo auseinanderlaufen.
;! Binare Baumstruktur (Vergleichsbaum).
auf paarweisen Vergleichen (also Anwendungen von
beruht, mit weniger als (n log n) Vergleichen
"\)
im
Worst Case auskommen?
Informatik II { Sommersemester 1999
235
Informatik II { Sommersemester 1999
236
Beispiel: Ausschnitt aus dem Vergleichsbaum fur Mergesort auf vier Elementen.
Fortsetzung Beispiel: Durchlauf durch einen einzelnen
Zweig des Vergleichsbaums
2 4
1
3
a1 a2 a3 a4
2
4
1
3
a 1 < a2 ?
nein
ja
2
ja
ja
nein
a1 < a3?
ja
1
3
nein
1
2
2
3 4
a1 < a4 ?
nein
a2 < a3?
ja
4
1
3
2< 4 ?
nein
1. Stufe links
ja
a1 < a4 ?
nein
ja
a2 < a4 ?
a2 < a4 ?
ja
4
a3 < a4 ?
a3 < a4 ?
1<3 ?
nein
1. Stufe rechts
ja
Fertig
ja
nein
ja
Fertig
2 <1?
nein
nein
Fertig
Fertig
Fertig
Fertig
2<3?
ja
2. Stufe
4<3?
nein
Fertig
Informatik II { Sommersemester 1999
237
Ergebnis soweit: Eine binare Baumstruktur mit mindestens so vielen Endknoten "Fertig\, wie es Permutationen von (a1; : : : ; an) gibt.
;! n! Endknoten.
Interessierende Groe: Die maximale Anzahl max(n)
von Vergleichen auf irgendeinem Pfad von oben nach
unten zu einem Endknoten (also die Hohe des Vergleichsbaumes).
A quivalente Umformulierung der Behauptung: Es
gilt max(n) 62 o(n log n) fur den Vergleichsbaum jedes
wahrhaft generischen Sortieralgorithmus.
Informatik II { Sommersemester 1999
238
Beweis von max(n) 62 o(n log n):
Erinnerung: Es gibt n! Endknoten.
Erinnerung: In einem binaren Baum mit m Endkno-
ten ist die durchschnittliche Hohe der Endknoten
mindestens blog2 mc.
;! max(n) blog2(n!)c
Umformung mit Logarithmengesetzen:
log2(n!) = log2
bnc
X
2
i=2
n !
Y
n
X
i=1
i=1
i =!
log2(i)
(log2(i) + log2(n ; i + 1))
(Letzter Schritt: zwei oder drei nichtnegative Summanden eliminiert und die verbleibenden Summanden
umgruppiert.)
Informatik II { Sommersemester 1999
239
Informatik II { Sommersemester 1999
240
Superadditivitat von log im Bereich (2; 1):
log2(i) + log2(n ; i + 1) log2(n + 1)
Interessantes Nebenresultat:
Erinnerung: Im Gegensatz zu Best und Worst Case
hangt der Average Case auch noch davon ab, mit
welchen Wahrscheinlichkeiten alle moglichen Eingaben auftreten.
Sei der Average Case durch die Annahme deniert,
i
n-i+1
da alle Eingaben der Lange n gleichwahrscheinlich
sind (uniforme Zufallsverteilung).
n+1
In diesem Fall gibt es keinen generischen Sortieral-
gorithmus, dessen Laufzeit auch nur im Average
Case 2 o(n log n) ist.
Zusammengefat fur genugend groe n:
max(n) blog2(n!)c
j n k Warum?
2 ; 1 blog2(n + 1)c
!
14 n log2(n) 2 (n log n)
Informatik II { Sommersemester 1999
241
Warum auch im Average Case nicht o(n log n):
Entscheidend ist in diesem Fall nicht die maximale,
sondern die durchschnittliche Anzahl von Vergleichen.
Also die durchschnittliche Hohe eines Endknotens
im zugehorigen Vergleichsbaum.
Schon die war aber im optimalen (namlich balancierten) Fall nicht besser als (n log n).
;! Vgl. Anfang von Thema 10.
Informatik II { Sommersemester 1999
243
Informatik II { Sommersemester 1999
242
Merke:
Die asymptotische Laufzeit eines generischen
Algorithmus hangt von der asymptotischen
Laufzeit der Basisoperationen ab, die er
"blind\ verwendet.
Die Gesamtkodierungslange fur n zu sortierende Elemente eines Datentyps kann im allgemeinen (n log n) im Worst Case werden.
Insbesondere kann grundsatzlich kein Sortieralgorithmus im Worst Case asymptotisch
schneller als (n log n) sein.
Ein wahrhaft generischer Sortieralgorithmus
kann beweisbar selbst dann im Worst Case
(oder im Average Case unter uniformer Zufallsverteilung) nicht schneller als (n log n)
sein, wenn der Aufwand fur einen Vergleich
(1) ist.
Informatik II { Sommersemester 1999
244
Thema 11: Container
Vorgehensweise:
Abstrakte Containertypen anhand von Anforderun-
Erinnerung:
Arrays konnen Sequenzen von Elementen eines be-
liebigen Typs speichern.
Speziell Array{Typ Object[] kann Objekte jeden
Klassentyps speichern (sogar beliebig gemischt in
einem einzigen Array{Objekt).
Klasse java.util.Vector ist eine Alternative zu
Object[], die auch Einf
ugen und Loschen von Elementen erlaubt.
gen an Zugrismoglichkeiten auf ihre Elemente denieren.
Konkrete Datentypen dann in dieses Schema einordnen.
;! Ein konkreter Datentyp kann durchaus
unter mehreren abstrakten Typen eingeordnet werden.
Wichtigstes Beispiel: Dictionaries
(auch assoziative Arrays genannt).
Denition: Ein Datentyp, dessen wesentliche Aufgabe
die Speicherung von irgendwelchen Elementen ist, ist
ein Container.
Heute: Containertypen systematisch betrachten und
klassizieren.
Informatik II { Sommersemester 1999
245
Dictionary:
246
Namensgebende Beispielanwendung:
Speichert eine beliebige endliche Sequenz aus Paaren von Objekten.
Jedes Paar besteht aus einem Schlussel (key) und
einer Information (value).
Jeder Schlusselwert darf nur einmal vorkommen.
Geforderte Zugrismoglichkeiten:
{ Einfugen eines neuen Paars.
{ Loschen eines Paars, das durch seinen Schlussel
identiziert wird.
{ Ausgabe der Information, die zu einem gegebenen
Schlussel gespeichert wird.
{ Durchlauf durch die momentan gespeicherten Elemente.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
247
Die Schlussel sind Worter (Strings).
Die Information zu einem Schlussel ist ein erklarender Text:
{ Zum Beispiel ebenfalls als String{Objekt direkt
abgelegt
{ oder nur der Name eines Files mit dem Text als
Inhalt.
Allgemein: Jede Art von tabellarischer Information mit
eindeutigem Suchschlussel.
Beispiel: Daten von Studierenden mit Matrikelnummer
als Suchschlussel.
Vergleiche: Vorlesungen zu Datenbank- und Informationssystemen.
Informatik II { Sommersemester 1999
248
Realisierung in Java:
Fortsetzung Erlauterungen
Klasse java.util.Dictionary
public abstract class Dictionary
{
public abstract Object put
(Object
Object
public abstract Object remove (Object
public abstract Object get
(Object
Ausnahmesituationen und Ruckgabewerte:
key,
info);
key);
key);
{ Falls key der Schlusselwort eines momentan ge-
speicherten Paars ist, wird die Information zu key
durch info uberschrieben, und die alte Information ist der Ruckgabewert.
{ Sonst ist null der Ruckgabewert.
{ Exception NullPointerException, falls
key==null oder info==null.
public abstract Enumeration keys
();
public abstract Enumeration elements ();
...
}
Erlauterungen:
fugt das Paar (key,info) ein.
remove l
oscht das Paar mit Schlusselwert key (falls
vorhanden).
get liefert die Information zum Schlusselwert key.
put
Informatik II { Sommersemester 1999
249
Object remove ( Object key )
Object get
( Object key )
Liefert jeweils die aktuelle Information zu key (oder
null, falls key momentan nicht gespeichert).
Informatik II { Sommersemester 1999
250
Muster zum Durchlauf:
Fortsetzung Erlauterungen:
Fehlt noch:
Dictionary dictionary = ...;
...
Enumeration elements ()
Enumeration keys
()
Exakter Ruckgabetyp: java.util.Enumeration.
Aufgabe von Enumeration: Durchlauf durch eine
Sequenz von Elementen organisieren.
Hier konkret:
{ keys erlaubt Durchlauf durch alle momentan gespeicherten Schlusselwerte,
{ elements durch alle zugehorigen Informationen.
Beide Arten durchlaufen die einzelnen Paare "im
Gleichschritt\, d.h. in exakt gleicher Reihenfolge.
Einschrankung: Wahrend eines Durchlaufs darf
nicht put oder remove fur das betreende
Dictionary{Objekt aufgerufen werden.
Informatik II { Sommersemester 1999
Object put ( Object key, Object info )
251
Enumeration keyEnum = dictionary.keys
();
Enumeration infoEnum = dictionary.elements ();
while ( keyEnum.hasMoreElements() )
{
Object key = keyEnum.nextElement();
Object info = infoEnum.nextElement();
// Mach' irgendwas mit Paar (key,info).
}
Erlauterung:
Mit hasMoreElements wird abgefragt, ob mindestens ein Element noch nicht durchlaufen wurde.
Falls ja, liefert nextElement eines davon
zuruck.
Falls nein, wirft nextElement Exception
java.util.NoSuchElementException.
Informatik II { Sommersemester 1999
252
Fallbeispiel: Ein sehr primitiver Dictionary{Typ auf
Basis von Object[]
ist.
Falls theKeys!=null ist, gilt
{
{
{
public Object put (Object key, Object info)
throws NullPointerException
{
...
}
public Object remove (Object key)
{
...
}
public Object get (Object key)
{
...
}
public Enumeration keys ()
{
...
}
public Enumeration elements ()
{
...
}
...
}
theKeys.length>=1,
theKeys.length==theInfos.length
und
theKeys[i]!=null und theInfos[i]!=null
fur alle i==0...theKeys.length-1.
Fur jedes i bilden theKeys[i] und theInfos[i]
ein Paar.
Methode ArrayDictionary.get:
public Object get (Object key)
{
if ( theKeys == null )
return null;
for ( int i=0; i<theKeys.length; i++ )
if ( theKeys[i] == key )
return theInfos[i];
return null;
}
253
Idee fur ArrayDictionary.put:
Informatik II { Sommersemester 1999
254
Methode ArrayDictionary.put mit Zusatzmethode
Falls
theKeys==null ist, werden theKeys und
theInfos als Arrays der Gr
oe 1 mit Inhalt key
bzw. info neu eingerichtet.
Falls
theKeys!=null und key==theKeys[i] f
ur
einen Index i gilt, wird theInfos[i] mit
info u
berschrieben und der vorherige Wert von
theInfos[i] zur
uckgeliefert.
Ansonsten wird theKeys bzw. theInfos durch ein
Array mit genau einer Komponente mehr ersetzt,
der alle alten Schlussel und Informationen sowie
zusatzlich key bzw. info speichert.
Informatik II { Sommersemester 1999
Es gilt theKeys==null genau dann, wenn
theInfos==null
public class ArrayDictionary extends Dictionary
{
private Object[] theKeys;
private Object[] theInfos;
Informatik II { Sommersemester 1999
Konsistenzbedingungen:
255
ArrayDictionary.insert:
public Object put (Object key, Object info)
throws NullPointerException
{
if ( key == null || info == null )
throw new NullPointerException();
if ( theKeys == null )
{
theKeys = new Object[1];
theInfos = new Object[1];
theKeys[0] = key;
theInfos[0] = info;
return null;
}
for ( int i=0; i<theKeys.length; i++ )
if ( theKeys[i] == key )
{
Object oldInfo = theInfos[i];
theInfos[i] = info;
return oldInfo;
}
insert (key, info);
return null;
}
Informatik II { Sommersemester 1999
256
Zusatzmethode ArrayDictionary.insert:
Idee fur ArrayDictionary.remove:
Falls
key nicht in theKeys auftritt (insbesondere
im Fall theKeys==null), wird null zuruckgeliefert,
public void insert (Object key, Object info)
{
Object[] theNewKeys
= new Object [theKeys.length+1];
Object[] theNewInfos
= new Object [theInfos.length+1];
for ( int i=0; i<theKeys.length; i++ )
{
theNewKeys[i] = theKeys[i];
theNewInfos[i] = theInfos[i];
}
theKeys = theNewKeys;
theInfos = theNewInfos;
theKeys[theKeys.length-1] = key;
theInfos[theInfos.length-1] = info;
}
Informatik II { Sommersemester 1999
und es geschieht nichts weiter.
Sonst wird theKeys bzw. theInfos jeweils durch
einen Array mit genau einer Komponente weniger
ersetzt, in dem alle Paare auer (key,info) weiterhin vorkommen.
Wenn das letzte Element entfernt wird: theKeys
und theInfos werden wieder auf null gesetzt.
257
Methode ArrayDictionary.remove mit Zusatzmethode ArrayDictionary.takeOut:
258
Zusatzmethode ArrayDictionary.takeOut:
public void takeOut (int index)
{
Object[] theNewKeys
= new Object[theKeys.length-1];
Object[] theNewInfos
= new Object[theKeys.length-1];
for ( int j=0; j<index; j++ )
{
theNewKeys[j] = theKeys[j];
theNewInfos[j] = theInfos[j];
}
for ( int j=index+1; j<theKeys.length; j++ )
{
theNewKeys[j-1] = theKeys[j];
theNewInfos[j-1] = theInfos[j];
}
theKeys = theNewKeys;
theInfos = theNewInfos;
}
}
public Object remove (Object key)
{
if ( theKeys == null )
return null;
for ( int i=0; i<theKeys.length; i++ )
if ( theKeys[i] == key )
{
Object oldInfo = theInfos[i];
if ( theKeys.length == 1 )
{
theKeys = null;
theInfos = null;
}
else
takeOut (i);
return oldInfo;
}
return null;
}
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
259
Informatik II { Sommersemester 1999
260
Zugehorige Enumerationsklasse:
Konsistenzbedingung fur ArrayEnumeration:
public class ArrayEnumeration implements Enumeration
{
private Object[] arrayReference;
private int
currentIndex;
Die Elemente von theKeys und theInfos an den
Indizes 0 : : :currentIndex sind genau die Elemente, die schon durch ArrayEnumeration.nextElement
zuruckgeliefert wurden.
public ArrayEnumeration (Object[] arrayReference)
{
this.arrayReference = arrayReference;
currentIndex = -1;
}
Achtung:
public boolean hasMoreElements ()
{
return arrayReference != null
&& currentIndex < arrayReference.length-1;
}
Falls zwischendurch Methode put oder remove des
zugehorigen ArrayDictionary{Objekts aufgerufen
wird, geht alles schief!
public Object nextElement ()
throws NoSuchElementException
{
if ( arrayReference == null )
throw new NoSuchElementException();
++currentIndex;
if ( currentIndex >= arrayReference.length )
throw new NoSuchElementException();
return arrayReference [currentIndex];
}
;! Begrundung fur die Einschrankung, da das Dic-
tionary wahrend einer laufenden Enumeration
nicht modiziert werden darf.
}
Informatik II { Sommersemester 1999
261
Informatik II { Sommersemester 1999
262
Thema 12: Lineare Implementationen von
Dictionaries
Merke:
Container sind Datentypen, deren "Daseins-
Obige primitive Implementation eines Dictionaries auf
Basis zweier Arrays kostet im Worst Case (n) Laufzeit
fur jeden Aufruf von get, put und remove.
zweck\ die Speicherung von Objekten ist.
In Java gibt es dafur unter anderem Arrays
sowie die Klasse java.util.Vector.
Dictionaries sind die grundlegende Organisationsform fur Informationssysteme aller Art.
Die abstrakte Klasse Dictionary ist der Prototyp fur Dictionaries in Java.
Das heit formal:
Fur n 2 N sei Tn die Worst{Case{Zeit fur einen
Aufruf von
get, put oder remove auf einem
ArrayDictionary{Objekt mit momentan gespei-
cherten Paaren.
n
Es gibt Konstanten c1; c2 > 0, so da
c1 n Tn c2 n
fur alle n 2 N gilt.
Frage: Geht es besser?
Informatik II { Sommersemester 1999
263
Informatik II { Sommersemester 1999
264
Erlauterung: Ein Objekt dieser Klasse garan-
Ansatz:
Die Arrays sind sortiert nach den Schlusselwerten.
Voraussetzung: Irgendeine Sortierreihenfolge ist auf
den Schlusselwerten deniert.
Realisierung: Wie ublich mit Implementationen von
Interface Comparator.
cmp.isLessThan(theKeys[i-1],theKeys[i])==true
get geht nun in (log n) Zeit im
Worst Case mit binarer Suche.
Vorteil: Methode
public Object get ( Object key )
{
if ( theKeys == null )
return null;
int first = 0;
int afterLast = theKeys.length;
while ( afterLast - first > 1 )
{
int median = ( afterLast - first ) / 2;
if ( cmp.isLessThan(key,theKeys[median]) )
afterLast = median;
else
first = median;
}
if ( theKeys[first] == key )
return theInfos[first];
else
return null;
}
Realisierung:
public class SortedArrayDictionary extends Dictionary
{
private Object[]
theKeys;
private Object[]
theInfos;
private Comparator cmp;
public SortedArrayDictionary ( Comparator cmp )
{
this.cmp = cmp;
}
...
}
Informatik II { Sommersemester 1999
tiert als zusatzliche Konsistenzbedingung gegenuber
ArrayDictionary, da f
ur alle
i==1...theKeys.length-1 gilt:
265
Analyse der binaren Suche:
Informatik II { Sommersemester 1999
266
Weitere Methoden von SortedArrayDictionary:
Schleifeninvariante: Vor und nach jedem Durchlauf
(auch dem letzten!) gilt:
{ afterLast > first.
{ Wenn key uberhaupt in theKeys gespeichert ist,
dann an einem der Indizes
first...afterLast-1.
Methode put darf das neue Element nicht einfach
ans Ende hangen, sondern mu es an der richtigen
Position im Array einfugen:
Schleifenvariante: Die Dierenz
afterLast - first
wird in jedem Durchlauf ungefahr\ halbiert
(genaues "Erbsenzahlen\ "ausgelassen).
Alle anderen Methoden konnen unmittelbar von
ArrayDictionary
;! Ungefahr log2 n Durchlaufe im Worst Case.
ebenso die Enumerationsklasse ArrayEnumeration.
;! (log n) Laufzeit im Worst Case.
Informatik II { Sommersemester 1999
ubernommen werden,
267
Informatik II { Sommersemester 1999
268
Bemerkung:
Alternative: Verzeigerungsstrukturen
Hier behandelte Variante erreicht auch im Best Case
Motivation: SortedArrayDictionary braucht wie
ArrayContainer (n) Laufzeit f
ur's Einfugen und
nichts Besseres als (log n) Laufzeit.
Einfache Variation erreicht (1) im Best Case: Prufe
einfach nach jeder Berechnung von median, ob
median nicht schon das gesuchte Element ist.
Ware vorteilhaft, falls die 50%, 25%, 75%{Quantile
etc. besonders haug auftreten.
;! Nicht sehr realistisch.
Fur eigentlich jede realistische Denition der Haug-
keitsverteilung ist der Average Case aber auch mit
dieser Modikation nicht besser als (log n).
Loschen eines Elements.
In Anwendungen, in denen die Schlusselmenge im
wesentlichen konstant bleibt und nur andauernd get
aufgerufen wird, ist das eigentlich kein Problem.
Fur andere Anwendungen mu man aber noch mehr
tun.
Konkrete technische Hurde:
Arrays konnen nicht beliebig wachsen oder schrumpfen.
Auch Verwendung von java.util.Vector lost das
Problem nicht: Methoden wie addElement haben
intern mehr Aufwand als man denkt!
Informatik II { Sommersemester 1999
269
Andere Idee:
270
Idee: Je eine verzeigerte Liste fur Schlusselwerte und
Informationen.
Die einzelnen Schlussel (bzw. Infos) sind
nicht mehr Komponenten von Arrays,
sondern eigenstandige, "freischwebende\
Objekte
und untereinander durch "Querreferenzen\
verzeigert.
Konsistenzbedingungen:
Beide Listen sind gleich lang.
Der Schlusselwert und die Information eines Paares
sind in theKeys bzw. theInfos an der gleichen
Position gespeichert.
Das letzte Listenelement verweist auf null anstelle
eines nachsten Elements.
Vorbetrachtung: Lineare Verzeigerung.
value
Hilfsmittel:
class Item
{
public Item
public Object
}
Informatik II { Sommersemester 1999
null
theKeys
next
next;
value;
value
Java{Package!
Informatik II { Sommersemester 1999
null
theInfos
Beachte: Zugri reduziert auf's eigene
next
271
Informatik II { Sommersemester 1999
272
In Java:
Intuition zu get: Situation nach zwei Durchlaufen
durch die Schleife.
public class LinearLinkedDictionary
{
private Item theKeys;
private Item theInfos;
currentKey
public Object get ( Object key )
{
Item currentKey = theKeys;
Item currentInfo = theInfos;
while ( true )
{
if ( currentKey == null )
return null;
if ( currentKey.value == key )
return currentInfo.value;
currentKey = currentKey.next;
currentInfo = currentInfo.next;
}
}
null
theKeys
currentInfo
theInfos
null
...
}
Informatik II { Sommersemester 1999
273
Informatik II { Sommersemester 1999
274
Realisierung von LinearLinkedDictionary.put:
Ideen fur LinearLinkedDictionary.put:
Beide Listen werden wie in get schrittweise simultan
durchlaufen.
Falls key dabei gefunden: Wie ublich Information
uberschreiben und alte Information zuruckliefern.
Ansonsten wird ein neues Paar (key,info) vorne an
theKeys und theInfos angef
ugt.
Warum vorne und nicht hinten oder irgendwo mittendrin?
Antwort: Technisch einfacher.
Dadurch vermiedene Komplikationen: Kommen
unmittelbar im Anschlu an die Behandlung
von LinearLinkedDictionary in der Variation
SortedLinearLinkedDictionary zum Vorschein.
Erinnerung:
Nach "new Item()\ gilt value==null und (der entscheidende
Punkt:) next==null.
Informatik II { Sommersemester 1999
275
public Object put ( Object key, Object info )
throws NullPointerException
{
if ( key == null || info == null )
throw new NullPointerException();
if ( theKeys == null )
{
theKeys = new Item();
theKeys.value = key;
theInfos = new Item();
theInfos.value = info;
return null;
}
Item currentKey = theKeys;
Item currentInfo = theInfos;
while ( currentKey != null )
{
if ( currentKey.value == key )
return currentInfo.value;
currentKey = currentKey.next;
currentInfo = currentInfo.next;
}
Item newKey = new Item();
// ***
newKey.value = key;
newKey.next = theKeys;
theKeys = newKey;
// +++
Item newInfo = new Item();
newInfo.value = info;
newInfo.next = theInfos;
theInfos = newInfo;
return null;
}
Informatik II { Sommersemester 1999
276
Ideen fur LinearLinkedDictionary.remove:
Intuition zu "***\ bis "+++\
Beide Listen werden wie in get schrittweise simultan
Ausgangsliste theKeys:
null
theKeys
Nach "newKey.next
= theKeys\:
newKey
null
theKeys
Nach "theKeys
= newKey\:
newKey
theKeys
Informatik II { Sommersemester 1999
null
277
Informatik II { Sommersemester 1999
278
Intuition:
Realisierung:
Fur den Fall "theKeys.value
public Object remove ( Object key )
{
if ( theKeys == null )
return null;
if ( theKeys.value == key )
{
Item returnValue = theInfo.value;
theKeys = theKeys.next;
theInfos = theInfos.next;
return returnValue;
}
Item keyBeforeCurrent = theKeys;
Item infoBeforeCurrent = theInfos;
while ( keyBeforeCurrent.next != null )
{
if ( keyBeforeCurrent.next.value == key )
{
Object returnValue
= infoBeforeCurrent.next.value;
keyBeforeCurrent.next
= keyBeforeCurrent.next.next;
infoBeforeCurrent.next
= infoBeforeCurrent.next.next;
return returnValue;
}
}
return null;
}
Informatik II { Sommersemester 1999
durchlaufen.
Falls key dabei nicht gefunden: Wie ublich null
zuruckliefern.
Ansonsten: Das jeweils "richtige\ Element aus jeder
der beiden Listen "ausklinken\.
Das heit:
{ Falls das erste Element zu entfernen: Einfach
theKeys auf theKeys.next bzw. theInfos auf
theInfos.next umbiegen\.
"
{ Falls ein anderes Element zu entfernen ist: Dieses
Element in beiden Listen "uberbrucken\.
;! Ein Verweis zum vorhergehenden Element wird benotigt.
;! Beim Durchlauf durch die Liste mu
man immer "einen Schritt zuruckbleiben\.
Nach "theKeys
== key\.
= theKeys.next\:
null
theKeys
Fur den Fall, da
keyBeforeCurrent.next.value == key\
"z.B.
im ersten Durchlauf durch die while{Schleife
schon erreicht wird.
Konkret nach "keyBeforeCurrent.next =
keyBeforeCurrent.next.next\:
keyBeforeCurrent
theKeys
279
Informatik II { Sommersemester 1999
null
280
Frage: Was passiert mit den "ausgeklinkten\ Elementen (den grauen auf der letzten Folie)?
Antwort:
Diese Objekte sind vom Programm aus nicht mehr
ansprechbar, da alle Verweise darauf "umgebogen\
wurden.
Problem: Wenn laufend Elemente mit new neu erzeugt und wieder ausgeklinkt werden, besteht bald
der gesamte verfugbare Speicherplatz aus solchen
"Leichen\.
;! Nichts geht mehr.
Losung in Java: Solche Objekte werden fruher oder
spater durch einen sogenannten Garbage Collector
aufgesammelt, und ihr Speicherplatz kann in new
wiederverwendet werden.
Garbage Collector: Unsichtbarer, unkontrollierbarer
Zusatzthread, der von Zeit zu Zeit automatisch
aufwacht und diese "Leichen\ einsammelt.
Informatik II { Sommersemester 1999
281
Zugehorige Enumerationsklasse:
public class LinearLinkedEnumeration
implements Enumeration
{
private Item currentItem;
public LinearLinkedEnumeration ( Item theItems )
{
currentItem = theItems;
}
public bool hasMoreElements ()
{
return currentItem != null;
}
public Object nextElement ()
throws NoSuchElementException
{
if ( ! hasMoreElements() )
throw new NoSuchElementException();
Object returnValue = currentItem.value;
currentItem = currentItem.next;
return returnValue;
}
}
Informatik II { Sommersemester 1999
282
Konsistenzbedingung:
Variation "sortierte Liste\
Verweis currentItem zeigt auf das erste noch nicht
durch Methode nextElement zuruckgelieferte Element.
Notwendig ist wieder einmal eine Sortierreihenfolge
;! Konstrast zu ArrayEnumeration.currentIndex!
(Klasse SortedLinearLinkedDictionary):
auf den Schlusselwerten.
;! Analog zu SortedArrayDictionary ein
Comparator{Objekt cmp, das im Konstruktor von SortedLinearLinkedDictionary
ubergeben wird.
Weitere Konsistenzbedingung gegenuber
LinearLinkedDictionary: theKeys ist nach der
cmp{Reihenfolge aufsteigend sortiert.
Beobachtung:
{ Methoden
get und remove
LinearLinkedDictionary
konnen sofort von
ubernommen wer-
den,
{ ebenso LinearLinkedEnumeration,
{ nur Methode put mu neu implementiert werden.
Informatik II { Sommersemester 1999
283
Informatik II { Sommersemester 1999
284
Ideen fur SortedLinearLinkedDictionary.put:
Realisierung mit Zusatzmethode
Falls das Dictionary momentan leer ist: Zu einer
Liste mit einem einzelnen Element machen.
Falls ansonsten key kleiner als der kleinste momentan gespeicherte Schlussel ist:
;! Wieder vorne einfugen.
Ansonsten: Direkt hinter dem groten Schlussel, der
kleiner als key ist.
Das heit: Unmittelbar zwischen
currentKey.next, falls
{
currentKey
und
cmp.isLessThan (currentKey.value, key)
== true und
{ entweder currentKey.next
== null oder
cmp.isLessThan
(key, currentKey.next.value)
== false.
Informatik II { Sommersemester 1999
285
Zusatzmethode
public Object put ( Object key, Object info )
throws NullPointerException
{
if ( key == null || info == null )
throw new NullPointerException();
if ( theKeys == null )
{
// Wie in LinearLinkedDictionary.put
// (einschl. return)
}
if ( cmp.isLessThan(key,theKeys.value) )
{
// Vorne einfuegen wie in
// LinearLinkedDictionary.put
// und dann return
}
return insert ( key, info );
}
Informatik II { Sommersemester 1999
286
Intuition:
SortedLinearLinkedDictionary.insert:
Nach "newKey.next
public Object insert ( Object key, Object info )
{
Item currentKey = theKeys;
Item currentInfo = theInfos;
while ( currentKey.next != null &&
cmp.isLessThan(key,currentKey.next.value) )
{
currentKey = currentKey.next;
currentInfo = currentInfo.next;
}
if ( currentKey.next != null &&
key == currentKey.next.value )
return currentInfo.next.value;
Item newKey = new Item();
newKey.value = key;
newKey.next = currentKey.next;
currentKey.next = newKey;
Item newInfo = new Item();
newInfo.value = info;
newInfo.next = currentInfo.next;
currentInfo.next = newInfo;
}
Informatik II { Sommersemester 1999
SortedLinearLinkedDictionary.insert:
= currentKey.next\:
currentKey
null
theKeys
newKey
Nach "currentKey.next
= newKey\:
currentKey
null
theKeys
newKey
287
Informatik II { Sommersemester 1999
288
Thema 13: Baumartige Implementationen von
Dictionaries ("Suchbaume\)
Merke:
Bei einer "naiven\ Implementation von Dic-
Hilfsmittel anstelle von Klasse Item:
tionaries durch Arrays ergibt sich (n) Aufwand fur Suchen im Worst Case und generell
fur Einfugen und Loschen im Best und Worst
Case.
Bei sortierten Arrays kann der Aufwand speziell fur Suchen durch binare Suche auf
(log n) im Worst Case reduziert werden.
Bei einer Implementation mit linearen Listen
ergibt sich (1) fur das Einfugen im Best
und Worst Case, aber (n) im Worst Case
fur Suchen und Loschen.
Bei sortierten Listen ist sogar alles (n) im
Worst Case.
Informatik II { Sommersemester 1999
class TreeNode
{
Object
value;
TreeNode left;
TreeNode right;
}
Idee: Jedes Element hat nun zwei unmittelbare Nachfolger.
;! Binarer Baum anstelle einer linearen Liste.
Wieder Sortierreihenfolge vorausgesetzt!
289
Intuition:
Informatik II { Sommersemester 1999
290
Konsistenzbedingungen:
Es gibt einen einzigen "Einstiegsknoten\, die Wurzel
(root) des Baumes.
value
left right
value
left right
Auf jeden Baumknoten auer der Wurzel gibt es
genau einen Verweis
Knoten des Baumes.
value
left right
left
oder
right
von einem
Jeder Baumknoten ist von der Wurzel aus durch
eine Sequenz von Schritten uber left- und right{
Verweise aus erreichbar.
Fur jeden Baumknoten
node haben alle Baumknoten im linken Nachfolgerbaum echt kleineren
Schlusselwert als node.value und alle Baumknoten
im rechten Nachfolgerbaum echt groeren Schlusselwert.
Informatik II { Sommersemester 1999
291
Informatik II { Sommersemester 1999
292
Konsequenz:
Methode get kann sich von oben nach unten von
Knoten zu Knoten "durchhangeln\.
In jedem Baumknoten treeNode wird
treeNode.value verglichen:
{ gleich ;! gefunden und stop,
{ kleiner ;! nach links weiter,
{ groer ;! nach rechts weiter.
key
mit
Java{Implementation:
public class TreeDictionary
{
private TreeNode
rootOfKeys;
private TreeNode
rootOfInfos;
private Comparator cmp;
public TreeDictionary ( Comparator cmp )
{
this.cmp = cmp;
}
...
Methode TreeDictionary.get:
public Object get ( Object key )
{
TreeNode currentKey = rootOfKeys;
TreeNode currentInfo = rootOfInfos;
while ( true )
{
if ( currentKey == null )
return null;
if ( currentKey.value == key )
return currentInfo.value;
if ( cmp.isLessThan(key,currentKey.value) )
{
currentKey = currentKey.left;
currentInfo = currentInfo.left;
}
else
{
currentKey = currentKey.right;
currentInfo = currentInfo.right;
}
}
}
}
Informatik II { Sommersemester 1999
293
Idee fur TreeDictionary.put:
Wie in
aus.
get
294
Realisierung mit Zusatzmethode
schrittweiser Abstieg von der Wurzel
Falls
key dabei gefunden: Wie u
blich Information
uberschreiben und alte Information zuruckliefern.
Vor dem Abstieg zum jeweils nachsten Baumknoten:
{ Prufen, ob dieser Baumknoten uberhaupt exi-
stiert.
{ Falls nicht: Genau an dieser Leerstelle den neuen
Baumknoten einhangen.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
295
TreeDictionary.insert:
public Object put ( Object key, Object info )
throws NullPointerException
{
if ( key == null || info == null )
throw new NullPointerException();
if ( rootOfKeys == null )
{
// Wie bei LinearLinkedDictionary.put
// (einschl. return-Anweisung)
}
return insert (key, info);
}
Informatik II { Sommersemester 1999
296
Zusatzmethode TreeDictionary.insert:
Idee fur TreeDictionary.remove:
public Object insert ( Object key, Object info )
{
TreeNode currentKey = rootOfKeys;
TreeNode currentInfo = rootOfInfos;
while ( true )
{
if ( cmp.isLessThan(key,currentKey.value) )
if ( currentKey.left == null )
{
{
currentKey.left = new TreeNode();
currentKey.left.value = key;
currentInfo.left = new TreeNode();
currentInfo.left.value = key;
return null;
}
else
{
currentKey = currentKey.left;
currentInfo = currentInfo.left;
}
else if ( cmp.isLessThan(currentKey.value,key) )
// Analog
else // d.h. falls key == currentKey.value
{
Object oldInfo = currentInfo.value;
currentInfo.value = info;
return oldInfo;
}
}
}
Informatik II { Sommersemester 1999
Das zu loschende Paar (key,info) wieder schritt-
weise von oben nach unten in theKeys und
theInfos simultan suchen.
Wie bei Listen die Verweise currentKey und
currentInfo immer einen Knoten zur
uckhinken\
lassen, damit der Verweis auf den zu" entfernenden
Baumknoten manipuliert werden kann.
Falls nicht gefunden: Wie ublich ohne weitere Aktion
null zur
uckliefern.
Sonst drei Falle fur die gefundenen Baumknoten
currentKey und currentInfo separat betrachten:
{ keine unmittelbaren Nachfolgerknoten,
{ ein unmittelbarer Nachfolgerknoten,
{ zwei unmittelbare Nachfolgerknoten.
297
Fallbehandlung:
hat zwei unmittelbare Nachfolger.
;!
Knoten 2
null
A
A
null
Beobachtung: Wenn ein Baumknoten einen rechten Nachfolger hat (z.B. Knoten 2), dann liegt der
Baumknoten mit dem nachsthoheren Schlusselwert im
rechten Nachfolgerbaum und hat selbst keinen linken
Nachfolger (Knoten 5).
Knoten 1
Knoten 1
298
Noch zu behandeln: Der zu loschende Baumknoten
Keine unmittelbaren Nachfolgerknoten
;! umstandslos loschen.
currentKey
Informatik II { Sommersemester 1999
null
Knoten 1
Genau ein unmittelbarer Nachfolgerknoten
;! wie bei Listen durch den Nachfolgerkno-
Knoten 2
E
ten ersetzen.
Knoten 4
Knoten 3
Knoten 1
Knoten 1
currentKey
Knoten 3
Knoten 2
C
null
Knoten 3
C
;!
A
D
B
Knoten 5
A
B
null
A
C
B
Informatik II { Sommersemester 1999
299
Informatik II { Sommersemester 1999
300
Losung:
Weiteren Verweis beforeNextHigherKey bis zum
unmittelbaren Vorganger von Knoten 5 weiter absteigen lassen.
Wert value von Knoten 2 wird mit dem Inhalt von
Knoten 5 uberschrieben.
Knoten 5 wird anstelle von Knoten 2 gema 2. Fall
ausgeklinkt.
Konsequenzen:
Genau die richtigen Werte verbleiben im Baum.
Die Konsistenzbedingungen fur die Baumstruktur
und die Sortierreihenfolge werden aufrechterhalten.
Knoten 1
beforeCurrentKey
Knoten 2
E
Knoten 4
Knoten 3
beforeNextHigherKey
A
D
B
Knoten 6
Knoten 5
F
null
C
Informatik II { Sommersemester 1999
301
Enumeration auf binaren Baumen:
Durch Fadelung der Baumknoten.
Informatik II { Sommersemester 1999
302
Genauere Erlauterungen:
Jeder Baum hat eine weitere Objektvariable
realRight
vom Typ boolean.
Bedeutung: realRight
null
null
null
null
null
null
null
== true, falls right auf
einen "richtigen\ Nachfolgerknoten zeigt oder
right == null ist (durchgezogene Pfeile in der
Zeichnung auf der letzten Folie).
null null
Es gilt right
ten.
Erste Erlauterung:
Abgesehen vom Knoten mit dem allerhochsten
Schlusselwert zeigt Objektvariable right bei jedem
Baumknoten auf einen anderen Baumknoten.
Der Zielknoten eines right{Verweises hat immer
hoheren Schlusselwert als der Knoten, von dem der
right{Verweis ausgeht.
Die neuen Ruckwartsverweise zeigen sogar immer auf den Baumknoten mit dem nachsthoheren
Schlusselwert.
Informatik II { Sommersemester 1999
303
== null
nur beim allerletzten Kno-
Suchen, Einfugen, Loschen: Verweis
nicht weiter verfolgt, falls realRight
right wird
== false.
Beim Einfugen und Loschen mu der betroe-
ne Baumknoten korrekt "ein-/ausgefadelt\ werden
(hier nicht genauer behandelt).
Informatik II { Sommersemester 1999
304
Java{Implementation:
Enumeration in Sortierreihenfolge:
Allererster Baumknoten: Soweit wie moglich von der
Wurzel aus nach links absteigen.
Jeweils nachster Baumknoten nach dem aktuellen
Baumknoten currentNode:
{ Zuerst uber right einen Schritt weitergehen.
{ Falls das ein "echter\ Verweis auf einen Nachfolger war (durchgezogener Pfeil): Danach noch
soweit wie moglich nach links weiter absteigen.
Konsistenzbedingung:
Wie bei LinearLinkedDictionary.
null
null
null
null
null
null
null
public class TreeEnumeration implements Enumeration
{
private TreeNode currentNode;
public TreeEnumeration ( TreeNode rootOfTree )
{
currentNode = rootOfTree;
while ( currentNode.left != null )
currentNode = currentNode.left;
}
public boolean hasMoreElements ()
{
return currentNode != null;
}
public Object nextElement ()
throws NoSuchElementException
{
if ( ! hasMoreElements() )
throw new NoSuchElementException();
Object returnValue = currentNode.value;
boolean descendLeft = currentNode.realRight;
currentNode = currentNode.right;
if ( currentNode != null && descendLeft )
while ( currentNode.left != null )
currentNode = currentNode.left;
return returnValue;
}
null null
}
Informatik II { Sommersemester 1999
305
Frage: Was ist denn nun gewonnen durch U bergang
von linearer zu binarer Struktur?
Antwort: Zunachst einmal noch gar nichts, weil der
Baum im Worst Case zu einer linearen Liste entarten
kann.
Informatik II { Sommersemester 1999
306
Erinnerung: Ein balancierter Baum hat Hohe log2 n.
;! Eine einzelne Such-, Einfuge- oder Loschoperation kostet (log n) Zeit.
Knoten 1
null
Knoten 2
null
Knoten 3
null null null null null null null null null null null null null null null null
null
Aber: Jede Einfuge- oder Loschoperation kann den
Baum potentiell ein kleines Stuck weiter aus der Balance bringen.
;! Auf Dauer doch wieder (n) im Worst Case.
Knoten n
null
Informatik II { Sommersemester 1999
null
307
Informatik II { Sommersemester 1999
308
Idee: Wenn man es schaen wurde,
beim Einfugen und Loschen eine gewisse Balance zu
halten,
so da der Zusatzaufwand fur dieses Balancehalten
aber immer noch (log n) pro Einfuge-/Loschoperation bleibt,
dann ist (log n) pro Such-/Einfuge-/Loschoperation
bis in alle Ewigkeit garantiert (n die momentane Groe
des Dictionaries zum Zeitpunkt der Operation).
Denkbare Kandidaten (inspiriert aus dem optimal
balancierten Fall):
Fur jeden Baumknoten unterscheiden sich die Knotenzahlen im linken und rechten Nachfolgerbaum
(A und B ) nicht sonderlich.
Die Hohen von A und B unterscheiden sich nicht
sonderlich.
Problem: Optimale Balance kann man anscheinend
nicht durchhalten.
;! Gesucht ist eine schwachere Denition von
Balance.
Stark genug, um (log n) pro Operation
zu garantieren.
Schwach genug, um mit (log n) Aufwand pro Operation aufrechterhalten zu
werden.
Informatik II { Sommersemester 1999
A
309
Informatik II { Sommersemester 1999
B
310
Tiefe Einsicht: Die Eigenschaft, da sich fur jeden
Baumknoten die Hohen der beiden Nachfolgerbaume
im Betrag um maximal 1 unterscheiden, ist geeignet.
Vorabbetrachtung: In einem Baum mit n Knoten gibt
Stichwort in der Literatur: Ein Suchbaum mit dieser
Eigenschaft ist ein AVL{Baum.
Beweis: Mit vollstandiger Induktion uber die Knotenzahl n 1.
Behauptung: Ein AVL{Baum mit n Knoten hat Hohe
(log n).
n = 1: 1 Blatt, kein innerer Knoten.
n > 1: Sowohl der linke als auch der rechte Teilbaum
Beweis: Nachste sechs Folien.
Informatik II { Sommersemester 1999
311
es mehr Blatter als innere Knoten (d.h. Knoten, die
keine Blatter sind).
der Wurzel hat jeweils fur sich mehr Blatter als
innere Knoten.
;! Fur beide Teilbaume zusammengezahlt ist die
Blatterzahl um mindestens 2 hoher als die
Anzahl innerer Knoten.
;! Zusammen mit der Wurzel immer noch mehr
Blatter als innere Knoten.
Informatik II { Sommersemester 1999
312
Nun Beweisansatz fur die Behauptung, da AVL{
Baume logarithmische Hohe haben
Zunachst: Besser als O(log n) geht nicht, da ein optimal balancierter Baum mit n Knoten (vgl. Thema 10)
Hohe dlog2(n)e hat und
kein anderer binarer Baum mit n Knoten geringere
Hohe hat.
Fortsetzung Beweis: Zu gegebener Hohe h betrachte
die AVL{Baume mit Hohe h, die minimale Knotenzahl
haben.
;! Heien in der Literatur Fibonacci{Baume.
Beobachtung: Bei jedem Baumknoten unterscheiden
sich in diesem Fall die Hohen beider Nachfolgerbaume
im Betrag um genau 1.
(Sonst konnte man noch einen geeignet gewahlten
Knoten wegnehmen, ohne da sich die Gesamthohe h
verringert oder die AVL{Eigenschaft verletzt wird.)
;! Es reicht, O(log n) anstelle von (log n)
zu zeigen.
Informatik II { Sommersemester 1999
313
Konsequenz: Rekursionsformel fur die Knotenzahl
n(h) eines Fibonacci{Baumes mit Hohe h.
81
<
n(h) = : 2
1 + n(h ; 1) + n(h ; 2)
fur h = 0;
fur h = 1;
fur h > 1:
314
Zwischenstand: AVL{Baume mit Hohe h haben mindestens fib(h) Knoten.
Aber: Eigentlich interessierte uns
nicht die Minimalknotenzahl in Abhangigkeit von
Hilfsbehauptung: Fur alle h 2 N gilt fib(h) n(h).
Begrundung: Vergleich der beiden Rekursionsformeln
fur n(h) bzw. fib(h).
Bemerkung: Eine einfache vollstandige Induktion zeigt
zudem n(h) 3 fib(h) ; 1.
;! Daher Begrisbildung Fibonacci{Baum.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
315
der Hohe,
sondern umgekehrt die Maximalhohe in Abhangigkeit von der Knotenzahl.
Also: Umkehrabbildung betrachten.
Kleines technisches Problem: Es gibt nicht um-
gekehrt zu jeder Knotenzahl m eine Hohe h mit
n(h) = m.
Losung: Fur m 2 N sei H (m) die grote Zahl h mit
n(h) = n(H (m)) m.
;! Die Hohe eines AVL{Baumes mit m Knoten
ist hochstens H (m).
Informatik II { Sommersemester 1999
316
Bisher erreicht: Abschatzung (log m) im Best und
Worst Case fur die Hohe von AVL{Baumen mit m
Zwischenstand auf der letzten Folie besagte:
n(h) fib(h).
Knoten.
Erinnerung: fib(k) 2 ((1:618:::)k).
Fehlt noch: Realisierungen von put und remove, die
;! Es gibt Konstanten m0 2 N und c > 0, so
da fur alle m m0 gilt:
jeden AVL{Baum garantiert wieder in einen AVL{Baum
uberfuhren.
m n(H (m)) fib(H (m)) c (1:618:::)H (m)
Beobachtung:
Wenn ein einziger Knoten eingefugt oder entfernt
;! H (m) log(1:618:::)( 1c m)
wird, kann die Hohendierenz von linkem und rechtem Teilbaum nirgendwo um mehr als 1 verletzt
werden,
und das auch nur entlang des Baumpfades von
der Wurzel bis zum eingefugten bzw. geloschten
Knoten.
;! H (m) 2 O(log m)
;! Beweis fertig.
Informatik II { Sommersemester 1999
317
Informatik II { Sommersemester 1999
318
Fall I: A ist mindestens so hoch wie B .
Basistechnik:
Rotation an einem einzelnen Baumknoten
;! Einfachrotation:
Annahmen
(ohne Beschrankung der Allgemeinheit):
Die AVL{Eigenschaft ist fur alle Knoten in A, B
und C erfullt.
Der linke Nachfolgerbaum von Knoten 1 (also "Knoten 2\ + A + B ) hat eine um 2 groere Hohe als C .
Knoten 1
Knoten 2
Knoten 1
C
A
Knoten 1
Knoten 2
B
A
B
C
Ergebnis: Knoten 1 und alle seine unmittelbaren und
mittelbaren Nachfolger erfullen die AVL{Eigenschaft.
Knoten 2
C
A
Informatik II { Sommersemester 1999
B
319
Informatik II { Sommersemester 1999
320
Fall II: ("Knoten 3\ + B + C ) ist um 1 hoher als A.
;! Doppelrotation:
AVL{Baumen:
Zuerst neues Element einfugen bzw. altes Element
Knoten 1
loschen wie bei TreeDictionary.
Knoten 3
Knoten 2
Danach jeweils AVL{Eigenschaft wieder an allen
Knoten 2
Knoten herstellen.
Knoten 1
Erinnerung: Nur die Knoten auf dem Baumpfad zum
D
eingefugten/geloschten Element sind betroen.
Knoten 3
A
A
B
Anwendung beim Einfugen und Loschen in
B
C
D
{ Der Pfad wird von unten nach oben (also
C
"ruckwarts\) durchlaufen.
{ Jeder Knoten, an dem die AVL{Eigenschaft verletzt ist, wird durch Einfach- bzw. Doppelrotation
wieder in Balance gebracht.
Ergebnis: Wieder AVL{Eigenschaft uberall
erfullt.
Informatik II { Sommersemester 1999
Konkrete Vorgehensweise:
321
Informatik II { Sommersemester 1999
322
Technisches Problem:
Beobachtung:
Woher sind bei einem Baumknoten die Hohen der
Bei einer Rotation andern sich diese Dierenzen
beiden Nachfolgerbaume bekannt?
Jeweils bei Bedarf berechnen wurde ja wohl alle
Bemuhungen um etwas Besseres als (n) pro Operation zunichte machen.
Hilfreiche Einsicht:
Die Hohen werden eigentlich gar nicht gebraucht,
sondern nur die Dierenz von linkem und rechtem
Nachfolgerbaum.
nur in den 2 bzw. 3 rotierten Knoten sowie in den
unmittelbaren und mittelbaren Vorgangerknoten.
Unter den rotierten Knoten sind die A nderungen
nach einfachen Regeln und in (1) Zeit berechenbar.
Die A nderungen bei den hoheren Knoten konnen
aufgeschoben und beim Durchlaufen des Baumpfades von unten zur Wurzel "mitgeschleppt\ werden (Details hier nicht behandelt).
Diese Dierenz kann fur jeden Knoten einfach als
zusatzliche Objektvariable gespeichert werden.
Informatik II { Sommersemester 1999
323
Informatik II { Sommersemester 1999
324
Beispiel fur die einfachen (1){ Regeln fur die Berechnung der Hohendierenz bei den rotierten Knoten: Einfachrotation mit Hohenverhaltnissen h(A) =
h(B ) + 1 = h(C ) + 1.
+2
+1
Knoten 1
Knoten 2
Knoten 2
A
B
A
B
Bei einer "naiven\ Implementation von Dic-
tionaries durch binare Baume ergibt sich doch
wieder (n) Aufwand fur Suchen, Einfugen
und Loschen im Worst Case.
Bei "halbwegs\ balancierten Baumen (z.B.
AVL{Baumen) reduziert sich dieser Aufwand
zu (log n).
Bei AVL{Baumen kann die denierende Balanceeigenschaft auch in (log n) Zeit pro
Einfuge- und Loschoperation aufrechterhalten werden.
Insgesamt kann man Dictionaries also in einer Form implementieren, so da Suchen,
Einfugen und Loschen jeweils (log n) Zeit
benotigt.
0
Knoten 1
C
Merke:
0
C
Andere Falle: Analog.
Informatik II { Sommersemester 1999
325
Informatik II { Sommersemester 1999
326
Thema 14: Vielwegbaume
Exkurs: Hintergrundspeicher
Interessierte Zusatzfrage:
Im eigentlichen Datenspeicher eines Computers
Bisher haben wir nur binare Baume betrachtet.
Waren Baume mit potentiell mehr als 2 Nachfolgern
pro Knoten nicht besser?
Antworten:
menfunktionen zu beliebigen Basen > 1 asymptotisch aquivalent sind (vgl. Thema 8).
Auch bei den Proportionalitatsfaktoren ist nicht
klar, welche Basis gunstig ist. (Suchschritt pro
Baumknoten wird aufwendiger!)
Asymptotisch bringt es gar nichts, da alle Logarith-
Aber: Vielwegbaume sind interessant fur den Fall, da
die Datenmenge zu gro fur den Hauptspeicher ist.
Informatik II { Sommersemester 1999
327
(Hauptspeicher) werden die Daten nur temporar
gehalten.
Spatestens, wenn der Computer heruntergefahren
wird, ist der Inhalt des Hauptspeichers verloren.
Fur permanente Datenhaltung sind Hintergrundspeicher zustandig.
U bliches Medium: Festplatten.
Entscheidender Punkt fur das Weitere:
{ Daten werden zwischen Haupt- und Hintergrundspeicher nicht Bit fur Bit oder Byte fur Byte
transferiert,
{ sondern in groeren Blocken (Seiten).
{ Momentan ublich: 1.024, 2.048, 4.096 oder 8.192
Byte pro Seite.
Informatik II { Sommersemester 1999
328
Problem:
In diesem Abschnitt der Vorlesung (Thema 14):
Die Laufzeit fur Datentransfer von oder auf Hinter-
Behandlung der wichtigsten Datenstruktur fur dieses
Momentan typischerweise: Ungefahr
Bedeutung: B{Baume (bzw. Variationen von B{
Konsequenz:
Aber: Nur das abstrakte Prinzip von B{Baumen
grundspeicher ist um Groenordnungen groer als
die Laufzeit fur interne Elementaroperationen.
Szenario: B{Baume.
Baumen) sind das Ruckgrat jedes ernstzunehmenden Datenbanksystems.
Faktor 10.000 | 1.000.000.
Minimierung der Zugrie auf den Hintergrundspeicher pro Such-, Einfuge und Loschoperation ist in
diesem Szenario absolut vordringliches Optimierungsziel.
wird hier behandelt.
Warum: Die exakten Details sind zu umfangreich
und komplex.
Die bisher betrachteten Elementaroperationen fallen
im Vergleich nicht weiter ins Gewicht.
Informatik II { Sommersemester 1999
329
Idee:
Jeder Baumknoten kann bis zu k verschiedene Ele-
mente speichern.
Die Anzahl der unmittelbaren Nachfolger ist um
genau 1 groer als die Anzahl der gespeicherten
Elemente.
Die Konstante k wird so gewahlt, da k Elemente
und k + 1 Verweise zusammen gerade noch auf eine
Seite passen.
Informatik II { Sommersemester 1999
Konsistenzbedingungen (nur am Beispiel):
Fur jeden Schlussel x aus A gilt x < a.
Fur jeden Schlussel x aus B gilt a < x < b.
Fur jeden Schlussel x aus C gilt b < x < c.
...
Fur jeden Schlussel x aus F gilt e < x < f .
Fur jeden Schlussel x aus G gilt f < x.
Illustration: Einzelner Baumknoten mit k = 9,
Schlusselwerten a, b, c,: : :, f und Nachfolgerbaumen
A; : : : ; G.
a
b
c
d
e
330
a
b
c
d
e
f
null null null
f
A
B
C
D
E
F
G
null null null
A
B
C
D
Informatik II { Sommersemester 1999
E
F
G
331
Informatik II { Sommersemester 1999
332
Konsequenz aus den Konsistenzbedingungen:
Wie bei TreeDictionary konnen sich get, put und
von oben nach unten zur richtigen Stelle im
Baum "durchhangeln\.
In jedem Baumknoten mu der Suchschlussel mit
bis zu k Schlusselwerten verglichen werden.
Der "richtige\ unmittelbare Nachfolgerknoten kann
allein durch Vergleich des Suchschlussels mit den
Schlusselwerten des Baumknotens ermittelt werden
(d.h. ohne Ansehen der Nachfolgerknoten).
remove
Ergebnis:
Herausforderung: Gleichzeitig folgende Ziele errei-
chen...
Alle Baumknoten ausreichend ausgelastet.
Hohe wie bei AVL{Baumen logarithmisch beschrankt.
Aufrechterhaltung dieser beiden Eigenschaften bei
Einfugen und Loschen erfordert den Zugri auf
moglichst wenige (und immer noch nur logarithmische viele) weitere Baumknoten.
Guter Kompromi: B{Baume
Die Anzahl der Zugrie auf den Hintergrundspeicher
Denition: Ein B{Baum der Ordnung k (k gerade) ist
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
kann sich in Abhangigkeit von k massiv reduzieren.
Voraussetzung: Die einzelnen Baumknoten sind gut
ausgelastet\, das heit enthalten nicht wesentlich
"weniger
als k Schlusselwerte.
333
ein Vielwegsuchbaum wie oben beschrieben, so da
alle Blatter gleiche Hohe haben,
jeder Baumknoten auer der Wurzel mindestens k=2
und hochstens k Schlusselwerte enthalt und
die Wurzel mindestens einen und hochstens k
Schlusselwerte enthalt.
334
Behauptung: Die Hohe eines B{Baumes der Ordnung
k mit n gespeicherten Schlusselwerten ist in (log n).
Beweis der Hilfsbehauptung: Vollstandige Induktion
uber h.
Notation: H (T ) bezeichnet die Hohe des Baumes T .
hochstens k Schlusselwerte in der Wurzel (Hohe 0).
;! Mindestens 2 = 2 (: : :)0 und hochstens
k + 1 = (k + 1)1 Knoten auf Hohe 1.
Hilfsbehauptung: Fur h 2 f1; : : : ; H (T )g gibt es in
einem B{Baum T der Ordnung k mindestens
h ; 1
2 k2 + 1
Induktionsverankerung h = 1: Mindestens ein und
Induktionsschritt (h ; 1) ;! h > 1: Jeder Knoten
auf Hohe h ; 1 > 0 hat mindestens k2 + 1 und
hochstens k + 1 unmittelbare Nachfolger.
;! Mindestens
und hochstens (k + 1)h Knoten.
k
2
2 k h ; 23 k h ; 1
5 = 2 + 1
+ 1 42 + 1
2
2
und hochstens (k + 1) (k + 1)h ; 1
= (k + 1)h Knoten auf Hohe h.
Informatik II { Sommersemester 1999
335
Informatik II { Sommersemester 1999
336
Konsequenz: In einem B{Baum T der Ordnung k
enthalt jede Hohenstufe h 2 f1; : : : ; H (T )g minde k h ; 1
stens
k 2 +1
und jede Hohenstufe h 2 f0; : : : ; H (T )g hochstens
k (k + 1)h Schlusselwerte.
Begrundung: Obere und untere Abschatzung aus
der Hilfsbehauptung fur die Anzahl Baumknoten pro
Hohenstufe mit den oberen und unteren Schranken
(k=2 bzw. k) fur die Anzahl Schlusselwerte pro Baumknoten multiplizieren.
Nachstes Ziel:
Darauf aufbauend obere und untere Abschatzun-
gen fur die Gesamtzahl n(T ) von Schlusselwerten in
einem B{Baum T der Ordnung k in Abhangigkeit
von der Hohe berechnen.
Durch Umstellung Abschatzungen fur die Hohe in
Abhangigkeit von der Knotenzahl nden.
Informatik II { Sommersemester 1999
337
HX
(T )
h=0
k (k + 1)h = k HX
(T )
HX
(T ) k +1 h;1
h=1 2
H (X
T );1 = 1+k
k +1 h
2
h=0
(Formel fur geometrische Folgen:)
; k + 1H(T ) ; 1
= 1 + k 2; k 2 +1 ;1
= 1+2
"
#
k + 1 H (T ); 1
2
H(T )
= 2 k2 + 1
;1
Informatik II { Sommersemester 1999
h=0
(k + 1)h
338
;1
;! H (T ) log( k +1)
n(T ) + 1 2
H (T )+1
= k (k +(k1)+ 1) ; 1; 1
= (k + 1)H (T )+1
H(T )
n(T ) 2 k2 + 1
(Formel fur geometrische Folgen:)
Informatik II { Sommersemester 1999
n(T ) 1 + k
Umgestellt jeweils nach der Hohe H (T ):
Obere Abschatzung:
n(T ) Untere Abschatzung:
2
n(T ) (k + 1)H (T )+1 ; 1
;! H (T ) log(k+1) (n(T ) + 1) ; 1
;1
339
Informatik II { Sommersemester 1999
340
Stand soweit: H (T ) 2 (log n(T )).
Umrechnung der Abschatzungskonstanten in den 2{
Logarithmus:
21 log(k+1) (n(T ))
1
2 log2(k + 1) log2(n(T ))
H (T ) log( k +1)
"
n(T ) + 1 2
2
2
log2
#
; 2 log 1(k + 1) log2(n(T ))
log2 k2 + 1
2
;1
Realistische Groenordnungen fur k:
k = 100 ;! [:::] 10%.
k = 1000 ;! [:::] 6%.
log( k +1)(n(T ))
=
Erinnerung (Thema 10): Die kleinstmogliche Hohe
eines binaren Baumes mit n Knoten tritt bei totaler
Balancierung auf, namlich log2(n).
Die grotmogliche Hohe eines B{Baumes unterscheidet sich davon etwa um Faktor 1= log2(k + 1).
Die grot- und kleinstmogliche Hohe eines B{
Baumes unterscheiden sich maximal um den Faktor
H (T ) log(k+1) (n(T ) + 1) ; 1
=
Auswertung:
;1k + 1 log2(n(T ))
2
Informatik II { Sommersemester 1999
341
Ideen fur BTreeDictionary.put:
Informatik II { Sommersemester 1999
342
Intuition: "g\ in ein volles Blatt einfugen
Suche von der Wurzel aus das Blatt, in das der neue
(gestrichelter Pfeil: null{Verweis)
Schlusselwert hineingehoren wurde.
a
b c
p q
d
r
Falls weniger als k Werte momentan in diesem Blatt
gespeichert sind: einfach einfugen und fertig.
e
f
h
j
i
k
l m n o
Ansonsten: Blatt in zwei Teile zerlegen und den
Schlusselwert (Median) zum nachst"hmittleren\
oheren Baumknoten weiterreichen.
a
b c
d
j
p q
r
Falls der auch schon voll war: Rekursiv weiter hochsteigen im B{Baum.
Informatik II { Sommersemester 1999
e
343
f
g
h
i
Informatik II { Sommersemester 1999
k
l m n
o
344
Falls beim rekursiven Hochsteigen die Wurzel erreicht
wird und die Wurzel ebenfalls voll ist:
Intuition: "d\ in die volle Wurzel einfugen
Wurzel wird ebenfalls in zwei Teile zerlegt.
Neue Wurzel wird angelegt.
Der mittlere Schlusselwert wird als einziger
a
Schlusselwert in der neuen Wurzel gespeichert.
b c
e
f
g
h
i
j
k
g
h
i
j
k
f
;! Daher die notwendige Ausnahme, da die Wurzel
nicht mindestens k=2 Schlusselwerte enthalten
mu.
a
b
c d
e
Beachte: Nur wenn entlang des Baumpfades von der
Einfugestelle bis zur Wurzel alle Knoten (einschlielich
Wurzel) voll sind, vergroert sich die Hohe des Baumes.
;! Also im Normalfall relativ selten.
Informatik II { Sommersemester 1999
345
Ideen fur BTreeDictionary.remove:
Zu loschenden Schlusselwert wie ublich absteigend
von der Wurzel aus suchen und loschen.
Falls danach noch mindestens k=2 Schlusselwerte
im betroenen Knoten sind: Fertig.
Ansonsten: Umkehrung der Zerlegungsoperation,
d.h. Verschmelzung von "Geschwisterknoten\.
Insbesondere: Ein Schlusselwert wird aus dem gemeinsamen unmittelbaren Vorganger heruntergezogen.
Falls der unmittelbare Vorganger nur k=2 Schlusselwerte hatte:
;! Analog zum Einfugen soweit wie notig im
Baum hochgehen und auf jeder Stufe eine
solche Verschmelzung durchfuhren.
Falls dabei die Wurzel leer wird:
;! Wurzel wird geloscht.
;! Einzige Situation, in der die Hohe des
B{Baumes reduziert wird.
Informatik II { Sommersemester 1999
347
Informatik II { Sommersemester 1999
346
Intuition zum Verschmelzen: "m\ loschen
a
e
f g
h
b
c d
j
i
a
e
b
f g
Informatik II { Sommersemester 1999
p
q r
k
l
c d
p
q
r
h
j
k
l
i
m n
n
o
o
348
Thema 15: Hash{Tabellen
Merke:
Bei der Verwaltung von Daten auf dem Hin-
Szenario:
tergrundspeicher ist nicht nur die Asymptotik
praktisch von Bedeutung, sondern auch die
genaue Zahl von Speicherzugrien.
Aus diesem Grund sind hier Vielwegbaume
interessant, in denen jeder Knoten eine Speicherseite ausmacht.
B{Baume bieten eine Mindestgarantie fur
die Auslastung jedes einzelnen Baumknotens
(=Speicherseite).
Daraus folgen im Verhaltnis zu binaren Baumen sehr gunstige Konstanten fur die logarithmische Asymptotik: Die maximale Hohe eines B{Baumes mit n Knoten ist immer noch
um einen (von der Ordnung des B{Baumes
abhangigen) Faktor kleiner als die minimale
Hohe eines binaren Baumes.
Informatik II { Sommersemester 1999
Nach dem Aufbau des Dictionaries sollen keine Elemente mehr eingefugt oder geloscht werden.
Vor Aufbau des Dictionaries ist schon die Gesamtzahl von zu speichernden Elementen bekannt.
;! Statisches Dictionary.
Bisheriges Resultat:
(log n) pro Operation im Worst Case
(Thema 13 und 14).
Keine Perspektive fur etwas Besseres als (log n)
im Average Case fur "realistische\ Haugkeitsverteilungen.
349
In diesem Abschnitt:
Eine Datenstruktur auf Arraybasis, fur die im Worst
Informatik II { Sommersemester 1999
350
Fahrplan:
Case nur (n) Aufwand pro Einfugeoperation beim
Aufbau bzw. pro Suchoperation garantiert werden
kann.
Durch eine "pseudozufallige\ Streuung (hashing)
der Elemente uber das Array zeigt jede "nichtpathologische\ Haugkeitsverteilung erfahrungsgema
ungefahr dasselbe Laufzeitverhalten wie eine reine
Zufallsverteilung.
Konsequenz:
{ Man braucht sich im Average Case keine Gedanken um die genaue Haugkeitsverteilung zu
machen,
{ sondern kann der Analyse einfach den idealisierten
Fall einer Zufallsverteilung zugrundelegen.
Ergebnis wird sein: In diesem speziellen Fall von
Average Case gilt (1).
Zuerst das Grundkonzept auf abstrakter Ebene be-
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
351
trachten (Durststrecke!).
Dann Zielvorstellungen uberlegen, wie dieses Grundkonzept sinnvoll mit Leben zu fullen ist.
Schlielich konkrete Beispiele zum Thema "mit Leben fullen\ betrachten.
352
Grundkonzept:
Konsistenzbedingungen:
Fur n 2 N zu speichernde Elemente werden Arrays
theKeys und theInfos mit Indexbereich 0 : : : m ;
1, eingerichtet: m 2 N , m n.
Falls an Index i 2 f0; : : : ; m ; 1g momentan
Es gibt eine Folge von Funktionen f0; f1; f2;
Sei x ein momentan gespeicherter Schlusselwert,
und sei i 2 f0; : : : ; m ; 1g der Index von x, das
: : : ; fm;1, von denen jede den Wertebereich fur
Schlusselwerte auf f0; : : : ; m ; 1g abbildet,
und zwar so, da fi(x) != fj (x) fur alle potentiellen
Schlusselwerte x und alle i; j 2 f0; : : : ; m ; 1g,
i=
6 j , ist.
;! Fur jeden momentan gespeicherten Schlusselwert x gibt es genau ein i 2 f0; : : : ; m ; 1g,
so da theKeys[fi (x)]
==
353
Idee fur HashDictionary.get:
ist, durch.
dabei auftritt:
fi(x)] zuruckliefern und fertig.
Falls statt dessen theKeys[fi(x)]
auftritt:
== null
;! Schlusselwert x ist gema Konsistenzbe-
Informatik II { Sommersemester 1999
354
;! Schlusselwert und Information in theKeys[fi(x)]
dingungen momentan nicht gespeichert.
bzw. theInfos[fi (x)] ablegen.
;! Einfach null zuruckliefern und fertig.
Informatik II { Sommersemester 1999
!= null.
ist, durchgehen.
Falls theKeys[fi(x)] == x dabei auftritt:
theInfos[fi (x)] mit Argument info u
berschreiben, alten Wert zuruckliefern und fertig.
Falls statt dessen theKeys[fi(x)] == null
auftritt:
;! Schlusselwert x ist gema Konsistenzbedingungen momentan nicht gespeichert.
f0(x); f1(x); f2(x); : : : soweit, wie es notig
== x
fj (x)]
theKeys[
Idee fur HashDictionary.put:
Wieder f0(x); f1(x); f2(x); : : : soweit, wie es notig
Fur einen gegebenen Schlusselwert x gehe
theInfos[
heit theKeys[fi (x)] == x.
Fur alle j 2 f0; : : : ; i ; 1g gilt dann
x ist.
Informatik II { Sommersemester 1999
Falls theKeys[fi(x)]
kein Element in den Arrays gespeichert ist, gilt
theKeys[i] == null.
Methode HashDictionary.remove: Ist im
eingangs formulierten Szenario irrelevant.
355
Informatik II { Sommersemester 1999
356
Frage: Was will man eigentlich erreichen?
Oen: Konkrete Denition der Funktionen
f0; f1; f2; : : :
Primitives Beispiel: fi(x) = i fur alle potentiellen
Schlusselwerte x.
Klare Antwort: Den Wert i mit theKeys[fi(x)] ==
x oder theKeys[fi(x)] == null moglichst klein halten (zumindest im Durchschnitt).
Beim Einfugen des i{ten Elements x sind
Vorbetrachtung: Wie mu fi deniert sein, damit fur
zwei beliebige Schlusselwerte x und y die Wahrscheinlichkeit einer Kollision fi(x) = fi(y) moglichst klein
;! Einfugen von n m Elementen kostet Lauf-
Einkleidung in eine weniger abstrakte Fragestellung:
Trauriges Resultat:
f0(x); : : : ; fi;2(x) schon besetzt.
zeit
2
n !
X
i=1
i =
n(n + 1) 2
; = n2
Wenn mit get nicht ausgerechnet immer nur auf ein
paar wenige, fruh eingefugte Elemente zugegrien
wird, dann kostet get auch im Average Case (n)
Laufzeit.
Informatik II { Sommersemester 1999
357
Wie gro ist die Wahrscheinlichkeit, da zwei beliebige Leute am gleichen Datum (Schaltjahre ignoriert)
Geburtstag haben?
Naheliegende Antwort:
Es gibt 365 365 mogliche Kombinationen.
Davon gibt es 365 Kombinationen mit gleichem
Datum.
1
;! 365
Informatik II { Sommersemester 1999
358
Anschlufrage: Wie mute die Wahrscheinlichkeits-
Kleines Problem:
verteilung sein, damit gleiches Geburtsdatum moglichst
unwahrscheinlich wird?
Die Rechnung ist richtig.
Aber die Antwort ist falsch!
Ansatz:
Warum:
Die implizite Voraussetzung, da alle Geburtsdaten
1:1:;31:12: gleichwahrscheinlich sind, stimmt nicht.
Im Fruhjahr werden mehr Kinder geboren als im
Herbst.
Frage: A ndert sich dadurch wirklich etwas am Ergebnis?
Trockene Antwort durch Extrembeispiel: Alle Kinder
werden am 1:1: geboren.
1
;! Wahrscheinlichkeit 1 statt 365
Informatik II { Sommersemester 1999
wird?
359
Reellwertige Variable x1; x2; : : : ; x365 2 [0; 1].
Forderung: x1 + x2 + + x365 = 1.
Interpretation: xi ist die Wahscheinlichkeit, da eine
Person am Datum Nr. i Geburtstag hat.
;! x2i ist die Wahrscheinlichkeit, da beide Personen am Tag i Geburtstag haben.
;! x21 + x22 + + x2365 ist die Wahrscheinlichkeit, da beide Personen an irgendeinem Tag
zugleich Geburtstag haben.
Ziel: Werte fur x1; : : : ; x365 so bestimmen, da
x21 + x22 + + x2365
minimal wird.
Informatik II { Sommersemester 1999
360
Behauptung: Das globale Minimum wird bei x1 =
x2 = = x365 = 1=365 angenommen.
Beweis:
Durch Widerspruch, das heit, die exakt gegenteilige
Behauptung wird zum Widerspruch gefuhrt.
Gegenteilige Behauptung: Lat sich ohne Beschrankung der Allgemeinheit vereinfachen zu x1 6=
x2 .
Wegen y + y + x3 + x4 + + x365 = 1 mit y :=
(x1 + x2)=2 reicht zu zeigen: Wenn x1 und x2
beide durch y ersetzt werden, ergibt sich eine echte
Verbesserung.
Ansatz mit 1. Binomischer Formel:
x + x 2
2
2
y +y = 2 12 2
;
= 21 x21 + 2 x1 x2 + x22
Informatik II { Sommersemester 1999
Umgestellt:
2 x1 x2 < x21 + x22
Zusammengefat mit 2. Binomischer Formel:
( x2 ; x1 )2 > 0
Aber: (x2 ; x1)2 > 0 folgt sofort aus der
Widerspruchsannahme x1 6= x2.
;! x21 + x22 + x23 + + x2365 >
y2 + y2 + x33 + + x2365
;! Beweis fertig.
361
Zuruck zu Hash{Tabellen und f0:
Informatik II { Sommersemester 1999
362
Idealisiertes Modell zur asymptotischen
Stand soweit: Ideal ware es, wenn jedes fi al-
le Schlusselwerte uniform uber den Indexbereich
f0; : : : ; m ; 1g "verstreuen\ wurde.
Problem:
{ Das wurde eine echte Zufallsstreuung erfordern.
{ Wenn man die gespeicherten Schlusselwerte mittels f0; f1; f2; : : : wiedernden will, mussen diese
Funktionen aber 100% deterministisch sein.
Abgeschwachte Zielsetzung: Finde Funktionen
f0; f1; f2; : : :, die
{ 100% deterministisch sind,
{ aber einer uniformen Zufallsverteilung
Analyse:
Seien i; j 2 f0; : : : ; m ; 1g.
Die Wahrscheinlichkeit, da fi(x) = j ist, ist gleich
1=m,
und zwar unabhangig von allen anderen Werten
fj (y) mit j 6= i und/oder y 6= x,
abgesehen davon, da weiterhin fi(x) 6= fj (x) fur
alle i 6= j gelten soll.
(Hintergrund: Vorlesungen zu Stochastik oder Statistik, Stichwort bedingte Wahrscheinlichkeiten.)
Behauptung: Einfugen und Suchen von n m Elementen kostet in diesem idealisierten Modell (1)
Laufzeit pro Operation.
"zum Verwechseln\ ahnlich sehen.
Informatik II { Sommersemester 1999
Also zu zeigen:
1 ; x2 + 2 x x + x2 < x2 + x2
1 2
1
2
1
2
2
363
Informatik II { Sommersemester 1999
364
Einschub: Was sagt diese Behauptung eigentlich aus?
Also:
Analogie aus der Physik: Fallgesetz
(1) Laufzeit ist 100% korrekt fur das idealisierte
Liefert 100% korrekte Berechnungen fur den ideali-
sierten Fall eines Massepunkts ohne Ausdehnung in
einem totalen Vakuum unter einem homogenen Gravitationsfeld und ohne die Wirkung weiterer Krafte.
Praktisch 100% korrekte Berechnungen fur Experimente unter "Laborbedingungen\.
Leidlich korrekte Berechnungen fur Szenarien, in
denen andere Einusse eine geringe Rolle spielen
(Ballistik, Flugbahnen im Weltraum...).
Modell.
;! Noch zu beweisen.
Auch noch praktisch korrekt, falls f0; f1; f2; : : : wie
uniforme Zufallsverteilungen "aussehen\.
Aber allgemein lat sich fur beliebige
f0; f1; f2; : : : nichts daraus folgern.
;! Siehe primitives Beispiel oben.
Vollig unbrauchbare Berechnungen fur Situationen
mit "alltagstypischer\ Komplexitat (Flug einer Vogelfeder
im Wind).
Informatik II { Sommersemester 1999
365
Beweis der Behauptung: Einfugen und Suchen in (1)
Laufzeit im Average Case.
Einfugen eines Schlusselwertes x und spateres er-
folgreiches Suchen von x kosten asymptotisch gleich
viel.
;! Einfugen mu im weiteren nicht
betrachtet werden.
Erfolgreiches und erfolgloses Suchen eines nichtge-
speicherten Schlusselwertes sind verschiedene Szenarien.
;! Fallunterscheidung.
Informatik II { Sommersemester 1999
366
Teilbehauptung I: Erfolgreiche Suche erfordert im
Durchschnitt die Auswertung von
1
1 ; mn+1 2 (1)
Funktionen f0; f1; f2; : : :
Bemerkung: Formaler Beleg fur die intuitiv logische
Erkenntnis, da die Wahrscheinlichkeit fur Kollisionen
(und damit die durchschnittliche Laufzeit) mit wachsendem Verhaltnis m=n nur kleiner wird.
Erinnerung:
{ 0; : : : ; m ; 1 Indexbereich der Arrays.
{ n m Anzahl der gespeicherten
Elemente.
Informatik II { Sommersemester 1999
367
Informatik II { Sommersemester 1999
368
Notation fur den Beweis von Teilbehauptung I:
pi: Wahrscheinlichkeit, da genau i Auswertungen
notig sind (i 2 f1; : : : ; mg).
;! Durchschnittliche Anzahl Auswertungen ist
n
X
i=1
i=1
qi =
p1 + p2 + p3 + p4 +
+ p2 + p3 + p4 +
+ p3 + p4 +
+ p4 +
i pi :
qi: Wahrscheinlichkeit, da mindestens i
Auswertungen notig sind.
+
+
+
+
n X
n
X
i=1 j =i
pi
pi
pi
pi
=
n
X
i=1
;!
369
Ansatz:
pj =
+
+
+
+
+ pn-1 + pn
+ pn-1 + pn
+ p n-1 + pn
+ p n-1 + pn
+ pi +
+ p n-1 + pn
+ pn-1 + pn
i -mal
;! qi = pi + pi+1 + + pn.
Informatik II { Sommersemester 1999
n
X
Beachte:
+ pn
i pi :
n
X
i=1
qi 2 (1) zu beweisen.
Informatik II { Sommersemester 1999
370
Allgemein:
q1 = 1 ist oensichtlich.
Mindestens zwei Auswertungen notwendig.
() theKeys[f0(x)] != x und
n
X
i=1
f0(x)] != null.
() theKeys[f0(x)] ist eines der n ; 1 momentan
gespeicherten Elemente 6= x von insgesamt m
theKeys[
Indizes im Hash.
;! q2 = n ; 1
qi =
n n;1 n;2
X
n;i+1
m;1 m;i+2
i=1 m
=
n iY
;1 n ; j
X
i=1 j =1
m;j+1
Nebenrechnung: Fur a < b und c 0 gilt
m
Mindestens drei Auswertungen notwendig.
() theKeys[f0(x)] ist eines der n ; 1 Elemente =
6 x von insgesamt m Indizes, und
theKeys[f1 (x)] ist eines der n ; 2 Elemente =
6 x von den restlichen m ; 1.
;! q3 = n m; 1 mn ;; 21
a;c a
b;c b
wegen (a ; c) b = a b ; c b a b ; c a = (b ; c) a.
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
371
372
Teilbehauptung II: Erfolglose Suche erfordert im
Durchschnitt die Auswertung von
1 2 (1)
1 ; mn+1
+1
Funktionen f0; f1; f2; : : :
Anwendung der Nebenrechnung:
n iY
;1 n ; j
X
i=1 j =1
!
m;j+1
n n i ; 1
X
i=1
m+1
=
nX
;1 i=0
n
m+1
i
Beweis:
q1 = 1 bleibt naturlich.
Gesuchter Schlusselwert x ist momentan nicht ge-
(Geometrische Reihe:)
1 n i
X
m+1
i=0
speichert:
;! k Auswertungen sind genau dann notwendig,
wenn theKeys[f0 (x)] ... theKeys[fk;2 (x)]
!= null ist.
Konsequenz:
n n ; 1 n ; k + 1
qk = m
m;1 m;k+1
1
= 1; n
m+1
;! Teilbehauptung I bewiesen.
Weiterer Beweis: vollig analog.
Informatik II { Sommersemester 1999
373
Typische Wahl der Funktionen f0; f1; f2; : : :
Informatik II { Sommersemester 1999
Einschrankung im folgenden zunachst: Schlusselwerte
sind naturliche Zahlen.
Praktische Einschrankung: Alle Funktionen sollten
nach einer einfachen Regel deniert sein.
Praktisch bewahrte Ideen fur Funktion f :
Grundidee in der Praxis:
f (x) := a x + b mit zwei festen Parametern
a; b 2 N .
Erfahrungsgema gute Streuung fur f0, wenn a, b
und m paarweise verschiedene Primzahlen sind.
Zwei Funktionen f und g mit Wertebereich N .
Fur jeden moglichen Schlusselwert x und jedes
i 2 f0; : : : ; n ; 1g wird gesetzt:
fi(x) := (f (x) + i g(x)) mod m.
Informatik II { Sommersemester 1999
374
f (x) := dm x ze mit einem festen Parameter
z 2 (0; 1).
Erfahrungsgema gute Streuungpfur f0, wenn z
ungefahr der "Goldene Schnitt\ ( 5 ; 1)=2 ist.
(Fur diese Erfahrung gibt es sogar mathematische
Evidenz, wird hier aber nicht behandelt.)
375
Informatik II { Sommersemester 1999
376
Erinnerung:
Andere Arten von Schlusselwerten
te f0(x); f1(x); : : : ; fm;1(x) paarweise verschieden
sein.
Wir hatten uns auf einen Spezialfall "eingeschossen\: fi(x) = (f (x) + i g(x)) mod m.
Beispiel: Strings
Ideen fur Funktion g:
Seien c0(S ); : : : ; c`(S);1(S ) die einzelnen Zeichen
Fur jeden Schlusselwert X sollen die Indexwer-
von ci.
Hashfunktion f :
Double Hashing: g wird ahnlich wie f deniert (aber
mit anderen Parameterwerten).
Erfahrung: Streuverhalten kommt dem Ideal einer
rein zufalligen Streuung sehr nah.
377
Warum Primzahlen: Je "primer\ die Parameter pi,
um so starker wird erfahrungsgem
a jedwede Besonderheit im Datenprol "zerhackt\.
Achtung: f (S ) kann sehr schnell Wertebereich von
oder sogar long uberschreiten.
Technischer Trick: Zwischendurch immer wieder einmal das momentane Zwischenresultat durch Modulobildung mit einer Primzahl q auf sichere Groenordnungen reduzieren.
int hashKey = 0;
for ( int i=0; i<S.length; i++ )
{
int indexOfPrimeNumber = i % r;
hashKey += int(S[i]) * p[indexOfPrimeNumber];
if ( hashKey > maxSafeNumber )
hashKey %= q;
}
Informatik II { Sommersemester 1999
Primzahlen.
Fur i 2 f0; : : : ; `(S ) ; 1g sei ai 2 N der ASCII{Wert
Keine gute Streuung wegen Haufungsbildungen:
f0(x) = f0(y) fur zwei Schlusselwerte x und y
;! fi(x) = fi(y) fur alle i.
int
Seien p0; : : : ; pr;1 paarweise verschiedene
eines Strings S der Lange `(S ).
Lineares Sondieren: g(x) = 1 fur alle x.
Informatik II { Sommersemester 1999
Idee:
379
f (S ) :=
`(X
S );1
i=0
ai p(i mod r)
Analog die Denition der additiven Hashfunktion g
(mit anderen Primzahlen).
Informatik II { Sommersemester 1999
378
Beispiele fur das Szenario "Statisches Dictionary\, auf
das Hash{Tabellen passen:
On{Line{Worterbuch:
{ Schlusselwerte: Die eingetragenen Worter.
{ Informationen: Die erklarenden Texte.
Speicher einer WWW{Suchmaschine:
{ Schlusselwerte: Alle in den durchsuchten WWW{
Seiten gefundenen Worter.
{ Informationen: Zu jedem indizierten Wort die Liste der URLs, in denen es gefunden wurde.
Informatik II { Sommersemester 1999
380
Merke:
Thema 16: Prioritatswarteschlangen
Die rein statische Variante von Dictionaries
(d.h. nach Aufbau kein Einfugen und Loschen
mehr) ist in vielen Anwendungen wichtig.
Implementationen von dynamischen Dictionaries wie AVL- und B{Baume garantieren
(log n) Aufwand pro Suche und (n log n)
fur den Aufbau.
Hash{Verfahren konnen im Worst Case nichts
Besseres als (n) pro Suche und (n2) fur
den Aufbau garantieren.
Erfahrungsgema ist der reale Aufwand aber
(1) pro Suche und (n) fur den Aufbau.
Durch das wilde "Zerhacken\ mittels Primzahlen ist das empirische
Laufzeitverhalten im
Average Case kaum sensitiv gegenuber dem
charakteristischen Datenprol einer konkreten
Anwendungssituation.
Informatik II { Sommersemester 1999
Wie Dictionaries eine Datenstruktur zum Speicher
von Paaren (Schlussel,Information).
Aber: Andere Semantik fur Schlussel.
{ Nicht zum gezielten Suchen eines gegebenen
Schlussels,
{ sondern als Prioritatswert fur die jeweils assozierte Information.
381
Mogliche Realisierung als Java{Interface:
public interface PriorityQueue
{
public Object insert
( Object
Object
public Object getFirstKey ();
public Object getFirstInfo ();
public void
removeFirst ();
public Object getKey
( Object
public void
changeKey
( Object
Object
}
Informatik II { Sommersemester 1999
382
Weitere Erlauterungen:
Methoden
getFirstKey bzw. getFirstInfo liefern den Schlussel bzw. die Information desjenigen
Paares, das momentan unter allen Paaren den kleinsten Schlusselwert (=die hochste Prioritat) besitzt.
key,
info );
Bei mehreren Kandidaten mit kleinstem
identification );
identification,
key );
Erlauterungen:
Methode insert fugt ein neues Paar ein und liefert
Schlusselwert:
{ Einer davon wird ausgewahlt.
{ Die Auswahl ist nicht festgelegt,
{ sondern kann in jeder Klasse, die das Interface
PriorityQueue jeweils implementiert, nach Gu"
sto\ sein.
eine anonyme Identikation dieses Paares zuruck.
Methode getKey liefert fur diese Identikation danach den Schlusselwert dieses Paares zuruck.
Methode changeKey uberschreibt den so identizierten Schlusselwert durch Parameter key.
Methode removeFirst loscht genau dieses Kandi-
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
383
datenpaar.
384
Beobachtung: Dictionary{Implementationen
lassen sich auch zur Realisierung von Priority Queues
verwenden.
;! Priority Queues lassen sich mittels AVL{
Baumen so implementieren, da jede
Operation (log n) Laufzeit bei n momentan gespeicherten Elementen erfordert.
insert: Wie put, nur da der Verweis auf das
eingefugte TreeNode{Objekt (Referenzvariable vom
Typ TreeNode) als Identikation zuruckgeliefert
wird.
getKey: Dann trivial.
changeKey: Erst loschen, dann mit neuem
Schlusselwert wieder einfugen.
Achtung: Damit die Identikation nicht falsch wird,
mu das neu eingefugte TreeNode{Objekt physisch
mit dem "ausgeklinkten\ identisch sein.
getFirstKey
, getFirstInfo und removeFirst:
Der Schlussel des "linkesten\ Elements im ganzen
Baum.
Informatik II { Sommersemester 1999
385
Begrundung:
Mit einer Priority Queue kann man sortieren.
Die Laufzeit fur diesen Sortieralgorithmus wird von
der Laufzeit fur diese drei Operationen auf der Priority Queue dominiert.
Selbst unter der Annahme, da der Vergleich zweier
Werte (1) ist, geht Sortieren aber grundsatzlich
nicht schneller als (n log n) im Average und Worst
Case (Thema 10).
Nebenresultat: Dieselbe Argumentation liefert fur
Dictionaries das analoge Negativresultat: Besser als
(log n) ist in jeder Implementation von Dictionaries
fur mindestens eine der Operationen nicht drin.
Informatik II { Sommersemester 1999
387
Frage:
Es wird nur ein Teil der Funktionalitat von Dictio-
naries verwendet.
Bei Hash{Tabellen konnte man diesen Tatbestand
ausnutzen, um etwas Besseres als (log n) zumindest im Average Case zu bekommen.
Kann man das auch bei Priority Queues erreichen?
Antwort: Selbst unter der idealisierten Annahme,
da jeder Vergleich nur (1) Zeit braucht, braucht
in jeder nur moglichen Implementation von Priority Queues mindestens eine der Operationen insert,
getFirstKey und removeFirst mindestens (log n)
Laufzeit schon im Average Case (erst recht im Worst
Case).
Informatik II { Sommersemester 1999
386
Sortieren durch Priority Queues
Technische Annahmen:
Klasse
MyPriorityQueue
PriorityQueue und
implementiert Interface
hat einen Konstruktor, der ein Comparator{Objekt
als Argument erhalt und intern zum Groenvergleich
von Schlusselwerten verwendet.
Idee: Die zu sortierenden Elemente sind die Suchschlussel (und die Information ist irrelevant und daher
einfach null).
public void sort ( Object[] A, Comparator cmp )
{
MyPriorityQueue queue = new MyPriorityQueue (cmp);
for ( int i=0; i<A.length; i++ )
queue.insert ( A[i], null );
for ( int i=0; i<A.length; i++ )
{
A[i] = queue.getFirstKey();
queue.removeFirst();
}
}
Informatik II { Sommersemester 1999
388
Frage: Ist damit das Thema Priority Queues nicht
erledigt?
Konkrete Konsistenzbedingungen:
Antwort: Man kann immer noch etwas an den Pro-
m + 1 Komponenten.
Die n momentan gespeicherten Elemente nden sich
an den Indizes 1; : : : ; n.
Heapeigenschaft: Fur alle i > 1 gilt
portionalitatsfaktoren und an der Kompliziertheit der
Datenstruktur verbessern.
Ergebnis wird sein: Eine Datenstruktur namens Heap.
Einschrankung: Es wird vorausgesetzt, da eine obere Schranke m fur die Anzahl zu speichernder Elemente bekannt ist.
;! Wird als weiteres Konstruktorargument vorab
ubergeben.
Im wesentlichen implementiert als Arrays theKeys
und theInfos.
Ein "Mittelding\ zwischen sortiertem und unsortiertem Array.
Informatik II { Sommersemester 1999
389
Array
theKeys
und
theInfos
i
A[ ]>=A[
Frage: Warum wird Index 0 ausgelassen?
Antwort: Allein aus notationellen Grunden, namlich
zur Vereinfachung der Formulierung der Heapeigenschaft.
Informatik II { Sommersemester 1999
390
Die besetzten Arrayindizes 1; : : : ; n werden Schicht
fur Schicht von links nach rechts den Baumknoten
zugeordnet.
Fur i > 1 ist Index bi=2c dann der unmittelbare
Vorganger von Index i im Baum.
;! Teilweise Sortierung des Arrays theKeys
(namlich entlang jedes Baumpfades).
theKeys[2]
theKeys[8]
theKeys[9]
Informatik II { Sommersemester 1999
theKeys[11]
125
178
141
475
141
255
143
222
144
876
365
597
401
An der Wurzel steht immer ein Element mit kleinsten Schlusselwert.
;! (1) Laufzeit fur getFirstKey und
getFirstInfo.
Der Baum ist vollstandig balanciert und hat (wie jeder vollstandig balancierte Baum) ungefahr doppelt
so viele Knoten wie Blatter (vgl. Thema 13).
;! Hohe 2 (log n) (vgl. Thema 10).
theKeys[3]
theKeys[10]
125
Beobachtungen:
theKeys[1]
theKeys[5]
bi=2c].
Zahlenbeispiel fur theKeys:
Intuition: als Baumstruktur
theKeys[4]
haben mindestens
theKeys[6]
theKeys[12]
theKeys[7]
theKeys[13]
theKeys[14]
391
Informatik II { Sommersemester 1999
392
Nachstes Ziel: Methode
Laufzeit.
changeKey
mit (log n)
Beispiel fur Hochtauschen: 876 ;! 150
Ausgangssituation:
125
Idee: Das Element mit verandertem Schlusselwert wird
im Heap Schritt fur Schritt
hochgetauscht, falls der Schlusselwert
verringert wurde und
hinabgetauscht, falls der Schlusselwert
erhoht wurde.
Abbruch: Sobald die Heapeigenschaft nicht mehr ver-
125
178
141
475
141
255
143
222
144
125
178
141
475
1. Austauschschritt:
141
255
143
222
144
178
143
394
150
144
222
365
597
150
125
141
401
475
;! Verletzung der Heapeigenschaft ist um eine
255
178
141
143
144
222
365
597
401
;! Keine Verletzung der Heapeigenschaft mehr.
;! Fertig mit Hochtauschen.
Stufe nach oben getauscht worden.
Informatik II { Sommersemester 1999
401
125
141
255
597
2. Austauschschritt:
125
475
150
365
Informatik II { Sommersemester 1999
125
141
401
125
Feinheit: Beim Hinabtauschen stehen im allgemeinen
zwei Nachfolger als Kandidaten zum Austausch zur
Verfugung.
;! Immer den kleineren von beiden nehmen.
393
597
Schlusselwert verringert:
letzt ist.
Informatik II { Sommersemester 1999
876
365
395
Informatik II { Sommersemester 1999
396
Beispiel fur Herabtauschen: 178 ;! 999
Ausgangssituation:
1. Austauschschritt:
125
125
125
178
125
141
141
222
222
365
141
475
255
143
144
876
597
141
365
999
401
475
255
143
144
876
597
401
Schlusselwert erhoht:
Immer der kleinere Nachfolger gewahlt:
125
125
141
475
141
255
;! Verletzung der Heapeigenschaft wird nicht du-
999
143
222
144
876
pliziert, sondern ist um eine Stufe nach unten
getauscht worden.
365
597
401
Informatik II { Sommersemester 1999
397
2. Austauschschritt:
398
Methode removeFirst:
Erinnerung: Die gespeicherten Elemente belegen die
Arrayindizes 1; : : : ; n.
125
125
141
Informatik II { Sommersemester 1999
;! Implementation eines Heaps braucht zur Iden-
tikation der belegten Indizes also nur eine
zusatzliche Objektvariable n.
222
141
365
597
Idee fur removeFirst:
475
255
143
144
876
999
401
Vertausche theKeys[1] mit theKeys[n] und
theInfos[1]
;! Keine Verletzung der Heapeigenschaft mehr.
;! Fertig mit Hinabtauschen.
mit theInfos[n].
Setze n = n-1.
Problem: theKeys[1] ist nun potentiell groer als
oder theKeys[3] und verletzt somit
die Heapeigenschaft.
;! Einfach wieder hinabtauschen.
theKeys[2]
Informatik II { Sommersemester 1999
399
Informatik II { Sommersemester 1999
400
Methode insert: Setze n = n+1 und fuge das neue
Element am neuen Index n ein.
Weiteres Problem:
;! Potentiell ist nun theKeys[n]<theKeys[bi=2c].
;! Einfach wieder hochtauschen.
Durch
Oen: Identikation von Elementen fur
Wie ndet man ezient eine freie Komponente?
changeKey.
getKey
und
Problem: Der Index eines Elements in theKeys und
andert sich und taugt daher nicht zur Identikation von auerhalb des Heaps.
theInfos
Losung:
Zusatzarray theIndexes mit gleich viel Elementen
removeFirst freigewordene Komponenten
in theIndexes mussen bei spateren insert's "recycelt\ werden.
Losung:
Freie Komponenten sind in einer Zusatzliste
theFreeSlots
untereinander verbunden.
wie theKeys und theInfos.
Je ein Eintrag mit festem Index fur jedes momentan
gespeicherte Element.
Inhalt: Momentaner Index des Elements in theKeys
und theInfos.
Einfugen einer freigewordenen Komponenten und
Informatik II { Sommersemester 1999
Informatik II { Sommersemester 1999
401
Intuition:
Herausnahme zur Wiederverwendung immer am Anfang der Liste (;! (1)).
402
Merke:
Priority Queues lassen sich als Spezialisierung
1
von Dictionaries interpretieren.
4
6
5
9
8
Implementationen von Priority Queues (und
3
2
10
11
12
erst recht Dictionaries) konnen grundsatzlich
nichts Besseres als (log n) im Average und
Worst Case fur die wesentlichen Methoden
erreichen.
7
13
14
Die Realisierung als Heap erreicht dies mit
12 2
6
3
9
0 11 7 0
8 10 4 13 0 14 0 1
5 0
0
recht kleinen Proportionalitatsfaktoren.
0
Bemerkung: Sortieren auf Basis von Heaps
theFreeSlots
Informatik II { Sommersemester 1999
ist in der Literatur als Heapsort bekannt.
null
403
Informatik II { Sommersemester 1999
404
Netzwerk:
Thema 17: Kurzeste Wege in Netzwerken
Offenburg
Ulm
Kontext: Der Algorithmus von Dijkstra ist eine gute
Beispielanwendung fur Heaps.
Gegeben:
Freiburg
{ Ein Netzwerk bestehend aus n Knoten und m
Kanten,
{ eine positive Lange fur jede Kante sowie
{ ein Start- und ein Zielknoten.
Lindau
Winterthur
Implementation von Netzwerken mit
(n + m) Speicherplatz:
Ein Array von Knoten.
Zu jedem Knoten ein Array von hinauszeigenden
Kanten.
Zu jeder Kante wird der Index ihres unmittelbaren
Zielknotens gespeichert.
Informatik II { Sommersemester 1999
405
Informatik II { Sommersemester 1999
406
Notation:
Intuition zur Implementation:
Informatik II { Sommersemester 1999
Meersburg
Friedrichshafen
Singen
Zürich
;! Vergleiche Ende von Thema 2.
13
14
15
16
Stockach
TitiseeNeustadt
Basel
Ein kurzester Pfad im Netzwerk vom Start- zum
Zielknoten.
Ulm :
Villingen-Schwenningen :
Winterthur :
Zürich :
Biberach
Donaueschingen
Konstanz
Gesucht:
Basel : 0
Biberach : 1
Donaueschingen : 2
Freiburg : 3
Friedrichshafen : 4
Konstanz : 5
Lindau : 6
Meersburg : 7
Offenburg : 8
Riedlingen : 9
Singen : 10
Stockach : 11
Titisee-Neustadt : 12
Riedlingen
VillingenSchwenningen
3
9
10
0
6
10
4
4
3
1
2
7
2
9
2
10
0
Eine Kante von u nach v wird mit (u; v) bezeichnet.
`(u; v) > 0 ist die Lange einer Kante (u; v), und
16
`(p) die Lange eines Pfades p.
Startknoten s, Zielknoten t.
Fur einen Knoten v sei s(v) die Lange eines
kurzesten Pfades von s nach v.
12 14
8 12
7
Beobachtung: Es endet genau dann ein kurzester
(s; v){Pfad mit der Kante (u; v), wenn `(u; v) =
s(v) ; s(u) ist.
Beweis:
11
14
11 13
5 11 15
9 10
3
s
p
u
v
Sei p ein kurzester (s; u){Pfad.
;! `(p) = s(u)
;! s(v) = `|(p)+{z`(u; v}) () `(u; v) = s(v) ; s(u)
Lange des Pfades "p + (u; v)\.
8
16
15
407
Informatik II { Sommersemester 1999
408
Konsequenz: Falls der Wert s(v) fur jeden Knoten
v bekannt ist, lat sich ein kurzester (s; t){Pfad von t
aus ruckwarts nach s konstruieren:
1. Starte mit i := 1, v1 := t und Pfad p := ;.
2. Solange vi 6= s, wiederhole:
(a) Suche eine Kante (vi+1; vi) mit
`(vi+1; vi) = (vi) ; (vi+1).
(b) Fuge (vi+1; vi) vorne an p an.
(c) Setze i := i + 1.
s=vk
vk-1
;! `(p) =
kX
;1
i=1
vk-2
v4
v3
v2
Technische Feinheit: Fur diese Ruckwartsberechnung
eines kurzesten Pfades aus den {Werten braucht man
eine umgekehrte Verzeigerung (d.h. jede Kante halt
einen Verweis auf ihren Ursprungsknoten).
Knotenbewertung berechnen:
Der eigentliche Algorithmus von Dijkstra
Basis: Reellwertige Variable (v) fur jeden
Knoten v.
t=v1
(s(vi) ; s(vi+1))
= s(v1) ; s(vk) = s(t)
Informatik II { Sommersemester 1999
409
Schleifeninvarianten nach i Durchlaufen:
(s) = 0 (anders gesagt: (s) = (s)).
(v) (v) fur alle Knoten s 6= v.
Informatik II { Sommersemester 1999
410
Intuition fur die Wellenfront:
Es gibt eine Partition der Knoten in
{ eine momentane "Wellenfront\ Wi,
{ die Menge Si aller Knoten, uber die die Wellen-
front schon hinweggegangen ist,
{ und die Restmenge Xi.
Die Menge Si besteht genau aus s und den i Knoten
v 6= s mit kleinsten Werten (v).
Wi besteht genau aus den Knoten v 62 Si, zu denen
eine Kante aus Si hinzeigt.
Fur jeden Knoten v 2 Si [ Wi ist (v) die Lange
eines kurzesten (s; v){Pfades, der (ggf. abgesehen
von v selbst) nur Knoten aus Si enthalt.
;! Am Ende, wenn die Wellenfront uber alle
Knoten hinweggegangen ist, gilt .
Informatik II { Sommersemester 1999
411
111111111111111111
000000000000000000
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
s
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
Informatik II { Sommersemester 1999
412
Initialisierung:
Kernschleife:
(s) := 0.
Fur jeden Knoten v mit Kante (s; v) wird gesetzt
Si entsteht aus Si;1 durch Einfugen des Knotens
v 2 Wi;1 mit minimalem momentanem Wert (v).
Fur jeden weiteren Knoten v wird (v) auf einen
Wi entsteht aus Wi;1, indem dieser Knoten v aus
(v) := `(s; v).
Wert gesetzt, der von der Implementation im weiteren als "1\ interpretiert wird, zum Beispiel
{ ein unmoglich groer Wert,
{ ein negativer und damit ganzlich
unmoglicher Wert.
Wi;1 entfernt wird und alle Knoten
w 62 (Si;1 [ Wi;1),
fur die es eine Kante (v; w) gibt, eingefugt werden.
Dabei wird jeweils gesetzt:
(w) := minf(w); (v) + `(v; w)g.
Konsequenz:
S0 = fsg.
W0 besteht aus allen Knoten, zu denen eine Kante
von s aus unmittelbar hinzeigt.
Informatik II { Sommersemester 1999
413
Korrektheit der Schleifeninvariante mit
vollstandiger Induktion:
Informatik II { Sommersemester 1999
414
Intuition zum Induktionsschritt:
Induktionsanfang: Ergibt sich sofort aus der Initialisierung.
Induktionsschritt: Alle Kantenlangen sind nichtnegativ.
;! Wenn ein Pfad teilweise uber Knoten
auerhalb von Wi;1 [ Si;1 verlauft,
kann er dadurch nur langer werden.
;! Fur den Knoten v 2 Wi;1 mit mini-
malem s(v) geht der kurzeste Pfad
ganz durch Si;1 [ Wi;1.
111111111111111111
000000000000000000
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
s
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
000000000000000000
111111111111111111
Aber: Nach Induktionsvoraussetzung ist die kurzeste Lange eines solchen Pfades gerade (v).
Informatik II { Sommersemester 1999
415
Informatik II { Sommersemester 1999
416
Laufzeit
Wellenfront Wi ist Inhalt einer Priority Queue:
{ Information: Knoten v.
{ Schlusselwert: (v).
Si wird uberhaupt nicht explizit verwaltet (wozu
Merke:
Semester ist zu Ende!
auch?).
Die Groe der Priority Queue ist durchgangig beschrankt durch die Gesamtzahl n von Knoten im
Netzwerk.
Jeder Knoten wird nur einmal in Wi eingefugt (also
auch nur einmal geloscht).
;! (n log n) fur alle insert's und
removeFirst's zusammen.
Jede der m Kanten im Netzwerk kann genau einmal
eine Reduzierung eines Wertes (v) provozieren.
;! (m log n) fur alle getKey's und
changeKey's zusammen.
Zusammengefat: ((n + m) log n)
Informatik II { Sommersemester 1999
417
Informatik II { Sommersemester 1999
418
Herunterladen