Skript mit Übungen (22.3.2010, von Paul Bußmann überarbeitet)

Werbung
Grundlagen der Informatik
Wolfgang Ertel, Paul Bußmann, Karl Glatz
23. September 2012
Hochschule
Ravensburg−Weingarten
Technik | Wirtschaft | Sozialwesen
Inhaltsverzeichnis
1 Was ist Informatik?
1.1 Informatik . . . . . . . . . . . . .
1.2 Computer . . . . . . . . . . . . .
1.3 Information . . . . . . . . . . . .
1.4 Teilgebiete der Informatik? . . . .
1.5 Programm, Algorithmus, Software
1.6 Betriebssysteme . . . . . . . . . .
1.7 Softwaretechnologie . . . . . . . .
1.8 Datensicherung . . . . . . . . . .
1.9 Datenschutz . . . . . . . . . . . .
1.10 Datenbanken . . . . . . . . . . .
1.11 Das Informatikstudium . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 Geschichte der Informatik
2.1 Wichtige Quellen . . . . . . . . . . .
2.2 Zahlendarstellung . . . . . . . . . . .
2.3 Geschichte der Bauelemente . . . . .
2.4 Geschichte der Rechenmaschinen . .
2.5 Geschichte der Programmiersprachen
2.6 Geschichte des Internet . . . . . . . .
2.7 Große Informatiker . . . . . . . . . .
2.8 Frauen in der Informatik . . . . . . .
2.9 Wichtige Institute und Firmen . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Algorithmen und Datenstrukturen – Einführung
3.1 Sortieren durch Einfügen . . . . . . . . . . . . . .
3.2 Quicksort . . . . . . . . . . . . . . . . . . . . . .
3.3 Sortieren mit Bäumen (Heapsort) . . . . . . . . .
3.4 Sortieren in linearer Zeit . . . . . . . . . . . . . .
3.5 Hashing . . . . . . . . . . . . . . . . . . . . . . .
4 Algorithmen auf Graphen
4.1 Einführung . . . . . . . . . . . . . .
4.2 Eulerkreise . . . . . . . . . . . . . . .
4.3 Datenstrukturen für Graphen . . . .
4.4 Kürzeste Wege . . . . . . . . . . . .
4.5 Das Problem des Handlungsreisenden
4.6 Planare Graphen . . . . . . . . . . .
.
.
.
.
.
.
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
4
5
5
6
7
7
9
9
10
10
.
.
.
.
.
.
.
.
.
12
12
12
13
14
19
20
20
25
26
.
.
.
.
.
27
27
34
39
45
45
.
.
.
.
.
.
50
50
52
54
55
59
66
5 Formale Sprachen und Endliche Automaten
5.1 Grundlagen . . . . . . . . . . . . . . . . . .
5.2 Grammatiken . . . . . . . . . . . . . . . . .
5.3 Reguläre Ausdrücke . . . . . . . . . . . . . .
5.4 Endliche Automaten zur Worterkennung . .
5.5 Automaten mit Ausgabe . . . . . . . . . . .
5.6 Formale Beschreibung von Automaten . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
68
68
70
72
74
75
75
6 Zusatzmaterial
78
6.1 Logarithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.2 Anwendung des Mastertheorems . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7 Übungen
7.1 Zahlensysteme . .
7.2 Sortieren . . . . .
7.3 Graphen . . . . .
7.4 Formale Sprachen
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
und Endliche Automaten
Literaturverzeichnis
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
80
80
80
83
84
87
3
Kapitel 1
Was ist Informatik?
1.1
Informatik
Definition 1.1 Informatik ist die Wissenschaft der automatischen Verarbeitung von Informationen.
(Am.: Computer Science)
Verschiedene Aspekte der Informatik:
•
•
•
•
1.2
Spaß am Programmieren (Erfolgserlebnisse)
Spaß an der Beherrschung der Maschine
Teilweise sehr abstrakte Wissenschaft (Mathematik)
Ohnmachtgefühl von Laien
Computer
Definition 1.2 Programmierbare Rechenmaschinen werden als Computer bezeichnet.
Früher wurden Menschen, die “rechnen” als Computer bezeichnet.
Computer
•
•
•
•
•
•
•
machen unser Leben bequemer
helfen beim Beschaffen von Informationen
vereinfachen die Kommunikation
können süchtig machen
können zum Pseudopartner werden
vernichten Arbeitsplätze
schaffen Arbeitsplätze
4
•
•
⇒
Wem nützt die Informatik?
Wem schadet die Informatik?
Soziale Verantwortung des Informatikers!
1.3
Information
Information: Wissen, Gegenteil von Unsicherheit.
Definition 1.3 Als elementare Maßeinheit für Information dient das Bit. Eine Nachricht
(z.B. ein Text od. eine Zahl) hat einen Informationsgehalt von n Bit, wenn die minimale Zahl
von Ja/Nein Fragen, zur exakten Ermittlung der Information genau n ist.
Ein Computer-Wort besteht z.B. aus 8, 16, 32, oder 64 Bit.
Beispiel 1.1
1
0
0
1
1
0
1
0
1 · 27 + 0 · 26 + 0 · 25 + 1 · 24 + 1 · 23 + 0 · 22 + 1 · 21 + 0 · 20 =
128 +
16 +
8+
2
=
154
1.4
Teilgebiete der Informatik?
Informatik
Einen guten Überblick über die verschiedenen Teilgebiete der Informatik verschafft das Wikipedia Informatik Portal. http://de.wikipedia.org/wiki/Portal:Informatik
Theoretische Informatik
•
•
•
•
•
•
•
•
Logik (logisch!)
Berechenbarkeit (ist jedes Problem berechenbar?)
Komplexität (Rechenaufwand)
Formale Sprachen (Programmiersprachen)
Informationstheorie (Datenübertragung)
Kryptographie (Datensicherheit)
Formale Spezifikation und Verifikation (Korrektheitsbeweise von Programmen)
...
Technische Informatik
•
•
Hardware
Rechnernetze
5
•
•
•
Schaltungen
Schnittstellen
Peripheriegeräte
Praktische Informatik
Bereitstellen von Hilfsmitteln für die Arbeit mit Computern
•
•
•
•
•
•
•
•
•
Rechnerarchitektur
Betriebssysteme (DOS, Windows, Unix, . . . )
Datenbanken
Künstliche Intelligenz
Software-Entwicklung
Datenkommunikation
Prozeßsteuerung
Bildverarbeitung
...
Angewandte Informatik
•
•
•
•
•
•
1.5
Wirtschaftsinformatik
Medizinische Informatik
Medieninformatik (Multimedia)
Kommunikationstechnik
Automatisierungstechnik
Künstliche Intelligenz
Programm, Algorithmus, Software
Definition 1.4
Algorithmus: Allgemeines Schema zur Lösung einer Klasse von Problemen.
Programm: Folge von Befehlen in einer festen Programmiersprache
Softwareentwicklung:
•
Problemanalyse
•
Problemlösung (Algorithmierung)
•
Programmierung (Kodierung)
•
Test
•
Inbetriebnahme
Softwaretechnologie:
Systematische Untersuchung der Softwareentwicklung und Bereitstellung von Entwicklungswerkzeugen.
6
1.6
Betriebssysteme
1.6.1
•
•
Betriebssysteme: Aufgaben
Laden u. Starten von Programmen
Verwalten des Hauptspeichers
◦
◦
•
Verwaltung von Dateien
◦
◦
•
Verwaltung von Dateiattributen (Größe, Datum, Rechte)
Verwaltung von Verzeichnissen
Ein- und Ausgabe
◦
◦
◦
•
Schützen der Speicherbereiche von Programmen
Verwaltung des virtuellen Speichers (paging, swapping)
Paging: Auslagern von Programmteilen
Swapping: Auslagern ganzer Programme
zeichenorientiert: Tastatur, Bildschirm, Drucker, serielle Schnittstelle
blockorientiert: Festplatte, Diskette, CD-Rom, Streamer
Verwaltung von Warteschlangen, z.B. f. Drucker
Zeitgeberfunktionen: Datum, Uhrzeit, verzögerter Programmstart
1.6.2
Betriebssysteme: Bestandteile
Betriebssystemkern: (Kernel) allgemeine Module f. Ein/Ausgabe, Speicherverwaltung, etc.
Dienstprogramme: kopieren, löschen v. Dateien, formatieren v. Disketten, ...
Bootprogramme: zum Hochfahren des Rechners benötigte Programme
ladbare Treiber: z.B. f. Netzwerkanbindung, Streamer
1.7
Softwaretechnologie
Kosten von Hard- und Software:
Früher: 90% Hardware, 10% Software
Heute: 10% Hardware, 90% Software
⇒
Informatik als Ingenieursdisziplin mit der Aufgabe der Softwareentwicklung!
Definition 1.5 Beim Softwareengineering laufen folgende Prozesse parallel nebeneinander
ab:
Softwareentwicklung
Projektmanagement
Qualitätssicherung
Projektverwaltung
7
1.7.1
Softwareentwicklung
Wichtige Begriffe:
•
•
•
Softwarelebenszyklus (software life cycle)
Phasenmodell der Softwareentwicklung
Wasserfallmodell
Planung
Der Softwarelebenszyklus
Spezifikation
Entwurf
Kodierung
Test
Betrieb
Stillegung
1.7.2
Moderne Softwareentwicklung
Unix-Pipe: ps | sort | lp
Wichtige Schritte im Entwicklungsprozess:
ps
Use Cases: Typische Benutzer-Programm Interaktionen
Prozeßliste
sort
Verteilungsmodell: Verteilung von Objekten/Prozessen auf einzelne Rechner, bzw. Teilnetze
sortierte Liste
lp
Datenflußdiagramm: Graphische Darstellung des Datenflusses.
Führt zu Schnittstellendefinitionen.
druckbare Daten
Drucker
Ausdruck auf Papier
1.7.3
CASE: Computer Aided SW-Engineering
CASE-Tools sind Werkzeuge, die den ganzen Entwicklungsprozeß unterstützen. Teile des
Prozesses können dabei automatisiert werden, andere benötigen eine Interaktion des Menschen
mit dem Tool.
Mehr Informationen auf case-tools.org.
8
1.8
Datensicherung
Eine wichtige Aufgabe beim Betrieb eines Rechensystems ist die Datensicherung.
Definition 1.6 Datensicherung (engl. Dump) ist das regelmäßige Speichern von Daten von
der Festplatte auf einen anderen Datenträger mit dem Ziel der Rekonstruktion bei Datenverlust.
klassisches Verfahren: inkrementeller Dump
Level 0 Dump: 1× pro Monat wird die gesamte Platte (inklusive Betriebssystem) auf dem
Magnetband gesichert. (in den ungeraden Monaten auf Band M-1, in den geraden Monaten auf Band M-2.)
Level 1 Dump: 1× pro Woche werden die Benutzerdaten von der Platte auf dem Magnetband
gesichert. (in den ungeraden Wochen auf Band W-1, in den geraden Wochen auf Band
W-2.)
Level 2 Dump: täglich werden die Benutzerdaten von der Platte auf dem Magnetband inkrementell gesichert. (in den ungeraden Wochen auf die Bänder Mo-1, . . . , Fr-1, in den
geraden Wochen auf die Bänder Mo-2, . . . , Fr-2)
Bemerkungen:
•
insgesamt werden 14 Magnetbänder für die Datensicherung benötigt!
•
während des Dumps sollte kein Benutzer auf dem Rechner arbeiten.
•
die gesicherten Medien (Bänder) sollten in einem anderen Gebäude sicher verwahrt werden.
modernes Verfahren:
Daten werden monatlich, wöchentlich, täglich auf je eine monatliche, eine wöchentliche, bzw.
eine tägliche Festplatte (im Wechsel) gespiegelt, nach ähnlichem Verfahren wie oben.
1.9
Datenschutz
Bundesdatenschutzgesetz (BGBL. 1 2003, S. 66) § 1, Abs. 1:
“Zweck dieses Gesetzes ist es, den Einzelnen davor zu schützen,
dass er durch den Umgang mit seinen personenbezogenen
Daten in seinem Persönlichkeitsrecht beeinträchtigt wird.”
Beispiel:
Die Veröffentlichung von Fotos von Mitarbeitern ist nur erlaubt, wenn der Mitarbeiter freiwillig und schriftlich sein Einverständnis erklärt.
9
Eva Müller
Mitarbeiterin des Monats
1.10
Datenbanken
Beispiele:
•
•
•
•
•
Literaturdatenbank
Personaldatenbank
Gefahrstoffdatenbank
Buchungssystem für Reisebüros/Fluggesellschaften
...
Definition 1.7 Eine Datenbank ist eine systematisch strukturierte, langfristig verfügbare
Sammlung von Daten einschließlich der zur sicheren und schnellen Manipulation dieser Daten
erforderlichen Software.
Vorteile einer Datenbank:
•
•
•
•
Mehrbenutzerbetrieb möglich
Unterschiedliche Sichten auf die Daten sind möglich
Daten sind unabhängig von Nutzerprogrammen; Nutzung ist unabhängig von der Art der
Speicherung.
Vollständigkeit (Integrität) und Korrektheit (Konsistenz) werden automatisch gewährleistet.
Eine Datenbank besteht aus
Datenbasis: die (z.B. als Tabellen) in Dateien gespeicherten Daten.
Datenbankmanagementsystem (DBMS): Programm für Aufbau, Verwaltung und Anwendung der Datenbank.
Datenbanksprache: formale Sprache zur Formulierung von Benutzeranfragen an die Datenbank. (Beispiel: SQL (Structured Query Language))
1.11
Das Informatikstudium
Leonardo da Vinci:
Studium ohne Hingabe schadet dem Gehirn
Der Studienerfolg wird statistisch u.a. bestimmt durch folgende Variablen:

Schnitt
falls Abitur

Schnitt − 0.5 falls FH-Reife direkt
Note: Note =

Schnitt − 1 falls FH-Reife auf 2. Bildungsweg
Interesse (für Informatik): Ich wollte schon immer wissen, wie (intelligente Roboter, Verschlüsselung, Internet, . . . ) funktioniert (0|1)
Biss (Wille): Wenn nötig arbeite ich auch am Abend und am Wochenende (0|1)
SozUm: Finanziell gesichert, Wohnen vor Ort, Partnerschaft o.k. (0|1)
10
1.11.1
Entscheidungsbaum
Variablenwerte für Interesse, Biss, SozUm:
1: trifft voll zu;
0: trifft nicht oder nur teilweise zu
Studienerfolg: −: keine Abschluss;
+: Bachelor;
++: Bachelor, sehr gut
Note
>3
Biss
0
Biss
0
1
+
<1.5
1.5-2.5
Interesse
2.5-3
1
0
1
+
Biss
Interesse
0
Interesse
0
0
1
0
1
+
++
+
++
SozUm
0
1
0
1
+
Biss
0
+
1.11.2
1
+
Score (einfach)
Score = (3 − Note) + 3 · Biss + 2 · Interesse + SozUm

 ++ falls Score > 3.5
+ falls Score > 0
Studienerfolg =

− falls sonst
11
++
SozUm
Interesse
1
1
Kapitel 2
Geschichte der Informatik
2.1
•
•
•
•
•
Wichtige Quellen
http://de.wikipedia.org
www.computerhistory.org
F. Naumann, Vom Abakus zum Internet [2]
H. Matis, Die Wundermaschine[3]
W. de Beauclair, Rechnen mit Maschinen – eine Bildgeschichte der Rechentechnik[4]
2.2
Zahlendarstellung
Additive Zahlendarstellung:
additiv (ohne Null)
–
1
11
111
1111
11111
111111
1111111
11111111
...
1111111111111111111111111111111111111111
mit Null (binär)
0
1
10
11
100
101
110
111
1000
...
110010
additive Zahlendarstellung ist für große Zahlen nicht brauchbar!
Mit n Stellen lassen sich darstellen:
additiv:
die Zahlen 1 . . . n
binär:
die Zahlen 0 . . . 2n − 1
dezimal:
die Zahlen 0 . . . 10n − 1
Ziffern 0 . . . b: die Zahlen 0 . . . (b + 1)n − 1
Wieviele Stellen braucht man, um eine große Zahl z darzustellen?
binär:
z = 2n
⇔
allgemein:
12
n = log2 z
dezimal
0
1
2
3
4
5
6
7
8
...
50
additiv:
binär:
dezimal:
Ziffern 0 . . . b:
Zahl d. Stellen um die Zahlen 0 . . . m darzustellen
m+1
≤ log2 m + 1
≤ log10 m + 1
≤ logb+1 m + 1
Die Zahl der Stellen bei Stellenwertsystemen wächst nur logarithmisch mit der Größe
der darzustellenden Zahl (dank der Null).
2.2.1
Geschichte der Zahlen und des Rechnens
30000 v. Chr. erste Zeichensysteme für Zahlen in Ägypten und Mesopotamien
3500 v. Chr. Zeichen auf Tontafeln in Pakistan
Additive Zahldarstellung in Rom, Mexiko (Maya), China, Ägypten, Sumerer
200 v. Chr
Erfindung der Null in Indien ⇒ Stellenwertsystem
0
Römische Schriftzeichen
1200
Fibonacci führt negative Zahlen ein (Schuld)
2.3
Geschichte der Bauelemente
2.3.1
Rechenlogik
Elektrische Rechenmaschine braucht elektrische Schalter!
Mechanik
Antike bis heute
Relais
1835 – 1950, J. Henry
Röhre
1904 – 1970, J.A. Fleming
(Engl.)
Transistor
1947 – heute, Bell Labs
(USA)
13
Integrierter
Schaltkreis
1958, heute bis zu 1 Milliarde Transistoren auf unter 1
cm2
Pentium 4
Intel, 2000, bis 3.8 GHz
Taktfrequenz, 2 CPUs auf
einem Chip
2.3.2
•
•
•
•
•
erste Festplatte
50 Platten, je 60 cm Durchmesser, 1200 Umdr./min
pro Platte 2 × 100 Spuren mit je 500 Zeichen
⇒ pro Platte 100 kB Speicher
gesamt: 5 MB Speicher
2.3.3
•
•
•
Speichertechnologie 2005
Mehr als 4 Gigabit pro cm2
Anzahl der Spuren pro Zoll (tpi) z. B. 135.000,
Köpfe fliegen 10-15 Nanometer über d. Platte
(Haar ist 50.000 nm dick)
2.3.4
2.4
Speichertechnologie 1956–2008
Geschichte der Rechenmaschinen
2.4.1
•
•
Speichertechnologie 1956, IBM-RAMAC
Kerbhölzer und Knotenschnüre
Speicherung von Zahlen
Additition und Subtraktion
14
2.4.2
Mechanische Rechenmaschinen (Mittelalter)
Analytical Engine
Abakus: +, −
Pascal (1641): +, −
kannt):
+,
−,
×,
/
1.
In der Programmierbarkeit einer Maschine durch
Die
grundlegend neuen
Ideenlange
bestehen:unbeSchickard
(1623,
Verwendung von Jacquard‘schen Lochkarten.
In der Weiterverwendung von
Zwischenergebnissen. („the engine eating its
own tail“)
3.
Der Aufteilung des Gerätes in Speicher(Store)
und Rechenwerk (Mill). Zahnstangen dienten der
Übertragung von Zahlenwerten zwischen Store
und Mill (Rechnerbus).
Bis 1948 (Speicherprogrammierbarkeit, John
von Neumann) gibt es keine grundlegende
Weiterentwicklung dieses Konzepts! Die
ersten „modernen“ Rechner hatten eine
einfachere Architektur.
2.
Die Analytical Engine war ein Papiercomputer. Nur
einzelne Komponenten (Teile des Rechenwerks)
wurden wirklich gebaut.
Leibniz (1675) +, −, ×, /
Babbage (1823), Difference Babbage (1833–?), Analytical
Informatikgeschichte, E. Ehses 2003
17
Engine
Engine (programmierbar!)
Der Abakus (ca. 2000 v.Chr. bis heute!)
•
•
•
die universale Rechenmaschine schlechthin!
Datenblatt
Analytical
Engine(bis heute), Rußland
verwendet in Griechenland,
Rom, der
Japan,
China
(bis heute)
heute in Japan: Wettbewerbe
Abakus
Taschenrechner
Speicher
für rund–100
Variable zu je 30-40 Stellen.
Die Analytical Engine
Vorrichtung zur Wiederholung von Operationen
(„mechanical means have been provided for backing
up or advancing the operation cards to any extend“)
Stanzer für Zahlenkarten (Massenspeicher).
•
•
•
Programmierbarkeit einer Drucker.
Maschine (revolutionär!) durch Verwendung von Jacquard’schen
Lochkarten.
Zeichengerät.
Weiterverwendung von Zwischenergebnissen.
(“the engine eating
Setzmaschine (offline).
its own tail”)
Addition und Subtraction vermutlich ca. 2 sec.
Multiplikation ca 1 min.und Rechenwerk (Mill).
Aufteilung des Gerätes in Speicher(Store)
Zahnstangen dienten der Übertragung von Zahlenwerten zwischen
Store und Mill (Rechnerbus).
Informatikgeschichte, E. Ehses 2003
15
18
Die Analytical Engine war ein Papiercomputer. Nur einzelne Komponenten (Teile des Rechenwerks) wurden wirklich gebaut. Bis 1948 (Speicherprogrammierbarkeit, John von Neumann)
gibt es keine grundlegende Weiterentwicklung dieses Konzepts! Die ersten modernen Rechner
hatten eine einfachere Architektur.
Eingabeschnittstelle für Lochkarten, unterschieden nach operation cards für die Befehlseingabe,
variable cards zur Eingabe von Variablen und ihrer Speicheradresse, sowie den number cards.
Ausgabeschnittstelle entweder für einen Drucker oder für Lochkarten die in die Bibliothek
eingereiht werden.
Die Chiffriermaschine Enigma
•
•
•
•
•
•
•
1923: Erfindung durch Arthur Scherbius zum Gebrauch
für Geschäftsleute.
1925: Deutsche Wehrmacht kauft Enigmas.
mehrfach geknackt (Polen) und wieder verbessert.
1939: Der Großangriff der Briten auf die Enigma in Bletchley Park.
1942: Neue Enigma mit vier Walzen ist wieder sicher
und wird im U-Boot-Krieg eingesetzt.
1943: Nach fast einem Jahr wird die 4-Walzen-Enigma
geknackt. Hier kam Colossus zum Einsatz.
1945: Entschlüsseln der Enigma-Codes war am Sieg der
Alliierten mit beteiligt. Ca. 10 000 Personen arbeiteten
in drei Schichten rund um die Uhr.
Zuse Z1, Z2
•
•
•
Baujahr 1938, 1939
Bleche schieben Stifte, Relais (Z2)
binär-dezimal
Konvertierung,
√
+, −, ×, /, ,
2.4.3
Operationen:
Elektrische Rechenmaschinen
Zuse Z3
Der im Flugzeugbau tätige Maschinenbauer und Bauingenieur Konrad Zuse (Berlin, 1910–1985)
erfand 1941 den ersten frei programmierbaren Rechner Z3.
16
•
•
•
•
•
•
•
•
Baujahr 1941
programmierbar über Lochstreifen
Ausgabe über Lampenfeld
Binäre Schaltlogik
“RISC”-Architektur: wenige Befehle
Gleitpunktarithmetik
Multiplikationszeit: 3 sec.
Hauptspeicher: 64 Worte à 22 Bit
ASCC (MARK 1)
•
•
•
•
•
•
•
•
H. Aiken will Rechner zum Lösen von DGLs
erster Rechner mit konsequenter vonNeumannArchitektur
Baujahr 1944, Univ. Harvard und IBM
programmierbar über Lochstreifen
Multiplikationszeit: 6 sec.
in Betrieb bis 1959
760 000 Einzelteile
15 m lang, 2.5 m hoch
Colossus
•
•
•
•
•
•
entwickelt u.a. von Alan Turing zum
Knacken von Enigma-Codes
Baujahr 1943,
programmierbar über Lochstreifen
photoelektr. Leser (5000 Zeichen/sec.)
Multiplikationszeit: 6 sec.
Original
1500 Röhren
Eniac (electronical numerical integrator and computer)
•
•
•
•
•
•
Baujahr 1946, Univ. Pennsylvania, USA
universell eingesetzt, in Betrieb bis 1955
Dezimalrechner, 10 Dezimalstellen
Taktfrequenz 100 kHz (Addition 0,2 ms)
18000 Röhren, 1500 Relais
Multiplikationszeit: 3 sec.
17
Nachbau
IBM 360
•
•
•
Baujahr 1964
Erster kommerziell erfolgreicher Großrechner
MTS: Michigan Time sharing system, 1966
Control Data CDC 6600
•
•
•
Erbaut 1964 von S. Cray
3 MIPS
verteilte Architektur, 10 I/O-Prozessoren
Telefunken TR 440
•
•
•
•
•
Baujahr 1970
6,50 m breit
Gewicht ca. 1250 Kg
Taktfreq. 20 MHz, 1.2 MIPS
1,5 MB Kernspeicher mit virtueller
Adressierung
CPU
Cray 1
•
•
•
•
•
•
Baujahr 1976
Vektorrechner
Supercomputer für numerische Berechnungen
64 parallel arbeitende 64-Bit Prozessoren
166 Mega-FLOPS
Gewicht: 2.5 Tonnen
Connection Machine
•
•
•
•
Baujahr 1986, D. Hillis of Thinking Machines Corp
Massiv parallel: 16000 parallele Prozessoren
ca. 10 Milliarden Operationen pro sec.
Anwendung in der KI, u.a. Neuronale Netze
18
Lochkartenstanzer
PCs
Commodore
Pet, Apple 2, 1977, 1 Main1977,
Kassetten- board, Farbgrafik
laufwerk, 4/8 kB
Hauptspeicher
2.4.4
IBM PC, 1981, 4.77 Commodore 64, 1981, für 595 US$ viel billiMHz Intel 8088, MS- ger als die Konkurrenz, TV-Bildschirm, KasDOS (Microsoft disc settenlaufwerk, 64 KB RAM
operating system)
Zitate
“I think there is a world market for about five computers.”
Thomas J. Watson Jr., chairman of IBM (1943)
“Where a calculator on the ENIAC is equipped with 18,000 vacuum tubes and weighs 30 tons,
computers in the future may have only 1,000 vacuum tubes and perhaps weigh 1 12 tons.”
Popular Mechanics (March 1949)
“640 K [of computer memory] ought to be enough for anybody.” Wird Bill Gates zugeschrieben,
der dies aber bestreitet.
2.5
•
•
Geschichte der Programmiersprachen
Heute gibt es über 2500 verschiedene Programmiersprachen
Siehe Aushang, bzw. www.levenez.com
prozedural: Assembler, Fortran (1954), PL/1, Basic, Algol, APL, C, Pascal, Cobol, Perl, PHP,
ADA
funktional: Lisp (1958), Haskell, Miranda, Mathematica
logisch: Prolog (1970)
objektorientiert: Simula 67, Smalltalk (1969), C++, Oberon, Java, C#
Fakultät in C, Prolog, Mathematica
C (prozedural):
1
2
3
4
5
6
7
8
9
int fakultaet(int n) {
int ergebnis = 1;
if (n > 1) {
ergebnis = n * fakultaet(n - 1);
}
return ergebnis;
}
19
Mathematica (funktional):
1
2
Fac[0] := 1;
Fac[n_] := n * Fac[n - 1]
Prolog (logisch):
1
2
fakultaet(1,1).
fakultaet(N,Res) :- N1 is N-1, fakultaet(N1,Res1), Res is N * Res1,
2.6
•
•
•
•
•
Geschichte des Internet
Gegründet 1962 durch die Advanced Research Projects Agency (ARPA) der USA (ARPANET).
Unter der Leitung von Bob Kahn und Vint Cerf entstehen 1973 das Transmission Control
Protocol (TCP) und 1976 das IP Protokoll in Form von RFC Dokumenten.
Erstes Email-Netz 1977 an der Univ. Wisconsin.
TCP/IP wird weltweit eingeführt
Tim Berners-Lee erfindet 1989 am CERN das World Wide Web (WWW)
“In the Beginning, ARPA created the ARPANET.
And the ARPANET was without form and void.
And darkness was upon the deep.
And the spirit of ARPA moved upon the face of the network and ARPA said, ’Let there be a
protocol,’ and there was a protocol. And ARPA saw that it was good.
And ARPA said, ’Let there be more protocols,’ and it was so. And ARPA saw that it was good.
And ARPA said, ’Let there be more networks,’ and it was so.”
– Danny Cohen
2.6.1
Aktuelle Trends (2012)
20
2.7
Große Informatiker
Blaise Pascal (Frankreich, 1623–1662)
•
baute als 18 jähriger für seinen Vater die erste funktionierende
mechanische Rechenmaschine zur Addition sechsstelliger Zahlen.
(Digitalrechner)
Gottfried Wilhelm Leibniz (Leipzig, 1646–1716)
•
•
•
•
Philosoph, Mathematiker, Diplomat, Bibliothekar
baut eine Rechenmaschine für alle vier Grundrechenarten.
Gründer der Akademie der Wissenschaften in Berlin
Erfindung der Dualzahlen
Charles Babbage (England, 1791-1871)
•
•
Entwickelt die Difference Engine zur Ableitung von Polynomen
(1823)
Entwickelt die Analytical Engine (1833)
Kurt Gödel (Österreich, 1906–1978)
Der Österreicher Kurt Gödel zeigt 1931
•
•
dass in der Prädikatenlogik erster Stufe alle wahren Aussagen
herleitbar sind.
In Logiken höherer Stufe hingegen gibt es wahre Aussagen, die
nicht beweisbar sind. Es lassen sich also nicht alle Berechnungsaufgaben automatisieren.
Zusammen mit Einstein arbeitet er auch an der Relativitätstheorie und
Kosmologie.
Denken Sie nach über die Aussage: ,,Ich bin nicht beweisbar” oder über ,,Die Menge aller
Barbiere, die all die Menschen rasieren, die sich nicht selbst rasieren.” oder über die
Menge {x|x ∈
/ x}.
21
Alan Turing (England, 1912–1954)
Der Brite Alan Turing leistet u.a. folgendes
•
Er erfindet 1935 das bis heute universelle Berechnungsmodell, die
“Turingmaschine”.
Er zeigt, dass es viele Funktionen gibt, die nicht berechenbar sind.
Er beweist das Halteproblem: Es kann kein Programm geben, das
in endlicher Zeit entscheidet, ob ein beliebiges Programm auf einer
Eingabe hält oder eine Endlosschleife hat.
Er definiert den Begriff der Intelligenz über den “Turing Test”.
•
•
•
•
•
•
Ende der Dreißiger Jahre macht er schon Vorschläge für lernfähige Computer.
Er ist im 2. Weltkrieg führend beteiligt an der Dechiffrierung der Enigma.
Er ist beteiligt am Bau von Colossus, dem ersten britischen Computer für die Dechiffrierung der Enigma (1944).
Er entwickelt einen Schachalgorithmus. Mangels Computer simuliert er auf Papier den
Computer und benötigt so etwa 90 Minuten pro Zug.
•
Denken Sie über folgendes Programm nach:
1
2
3
4
5
6
7
8
9
void foo(int n) {
if (runs_endlessly(foo, 0)) {
printf("Not executing foo, because it runs endlessly!");
else {
while (true) {
printf("Please wait...");
}
}
}
Lesekopf
Die Turingmaschine:
HAL LO
Z
Zustand
Claude Shannon (Michigan, 1916–2001)
•
•
•
•
A Mathematical Theory of Communication (1948)
Informationstheorie, Entropie als Informationsmaß
Formale Grundlagen der Kryptographie (Konfusion und Diffusion, 1949)
Entwickelt einen Schachcomputer (1960)
Alonzo Church (Washington, 1903–1995)
• Berechenbarkeit
• Lambda Kalkül
• Church’sche These: Die Turingmaschine kann alles berechnen, was
wir intuitiv für berechenbar halten.
22
John von Neumann (Polen, 1903–1957)
•
•
•
•
Spieltheorie, Minimax Algorithmus (1928)
Quantenmechanik, Entwicklung der Atombombe
von Neuman Architektur von Rechnern (EDVAC)
genial, lebenslustig, trinkfest
Die vonNeumann-Architektur
•
•
•
•
Zentraleinheit (CPU mit Rechen- und Steuerwerk)
Speicher (Hauptspeicher)
Bus (Busse)
Ein/Ausgabe (I/O) ⇒ Peripheriegeräte
CPU
Rechenwerk Steuerwerk
Speicher
(RAM)
I/O
Datenbus
Adressbus
Edsger Dijkstra (Rotterdem, Holland, 1930–2002)
• Algorithmen auf Graphen
• Kürzeste Wege Algorithmen
• Korrektheit von Programmen
Donald Knuth (Milwaukee, 1938–)
•
•
•
•
Meister der Algorithmen, u.a.: Zufallszahlen, Sortieren, Suche, ...
Autor der 5-bd. ,,Bibel”: The Art of Computer Programming
Erfinder des Textsatzsystems TEX
spielt eine selbstgebaute Orgel
Zitate: ,,Computer Programming is an art form, like the creation of poetry or music.”
,,I got into compilers because I thought the most amazing thing you could do with computers
was to have them write their own programs. When computing is applied to computing, that’s
when computer science reaches an ultimate completeness.”
Stephen A. Cook (Buffalo, New York, 1939–)
•
•
Begründer der modernen Komplexitätstheorie
NP-Vollständigkeit
Leslie Lamport (New York, 1941–)
• Theorie verteilter Systeme
• Lamport clock: partielle Ordnung der Zeit, keine globale Zeit
• Enwickler von LATEX(TEX-Macropaket)
23
Zitat: ,,When I look back on my work, most of it seems like dumb luck – I happened to be
looking at the right problem, at the right time, having the right background.”
Ken Thompson, Dennis Ritchie (New Orleans, 1943–, New York, 1941–)
•
•
1969: Erfindung von UNIX und C (Bell Laboratories, New Jersey, später AT&T)
Viele innovative Konzepte: Pipelining, verteilte Prozesse, Sockets, Timesharing und Prozesse mit Prioritäten (auch auf PCs)
Niklaus Wirth (Winterthur, Schweiz, 1934–)
•
•
Erfinder der Programmiersprachen Pascal (1970) und Modula
(1975)
Erfinder der Objektorientierten Sprache Oberon (1987)
Bill Gates (Seattle, 1955–)
•
•
•
•
•
brach nach zwei Jahren sein Studium in Harvard ab.
zus. mit Paul Allen Gründer von Microsoft
mit d. Kauf von MS-DOS 1980 durch IBM beginnt die Erfolgsstory von
Microsoft
1983 erscheint die erste Version des Betriebssystems Windows
reichster Mann der Welt (ca. 50 Mrd. US$)
Tim Berners-Lee (London, 1955–)
•
•
1989 schlug Berners-Lee seinem Arbeitgeber CERN (Europäisches
Kernforschungslabor) ein Projekt vor, das auf dem Prinzip des
Hypertexts beruhte und den weltweiten Austausch sowie die
Aktualisierung von Informationen zwischen Wissenschaftlern vereinfachen sollte.[1]
entwickelte den ersten Webbrowser, baute die erste Webseite
2.7.1
Der Turing Award
siehe www.acm.org/awards/taward.html
ACM’s most prestigious technical award is accompanied by a prize of $ 250,000.
Financial support of the Turing Award is provided by the Intel Corporation and Google.
ACM: Association of Computing Machinery
1966
1967
1968
1969
1970
1971
1972
1973
A.J. Perlis
Maurice V. Wilkes
Richard Hamming
Marvin Minsky
J.H. Wilkinson
John McCarthy
E.W. Dijkstra
Charles W. Bachman
Compilerbau
EDSAC, erster Computer mit internem Programmspeicher
Kodierung, Hamming-Distanz
Perzeptron, Neuronale Netze
Numerik
Künstliche Intelligenz, LISP
Graphenalgorithmen, ALGOL
Datenbanken
24
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
Donald E. Knuth
Allen Newell, Herbert A. Simon
Michael O. Rabin, Dana Scott
John Backus
Robert W. Floyd
Kenneth E. Iverson
C. Antony R. Hoare
Edgar F. Codd
Stephen A. Cook
Ken Thompson, Dennis Ritchie
Niklaus Wirth
Richard M. Karp
John Hopcroft, Robert Tarjan
John Cocke
Ivan Sutherland
William (Velvel) Kahan
Fernando J. Corbato
Robin Milner
Butler W. Lampson
Juris Hartmanis, Richard Stearns
Edward Feigenbaum, Raj Reddy
Manuel Blum
Amir Pnueli
Douglas Engelbart
James Gray
Frederick P. Brooks
Andrew Chi-Chih Yao
Ole-Johan Dahl, Kristen Nygaard
Ron Rivest, Adi Shamir, Leonard Adleman
Alan Kay
Vinton G. Cerf, Robert E. Kahn
Peter Naur
Frances E. Allen
E. Clarke, A. Emerson, J. Sifakis
Barbara H. Liskov
2.8
Algorithmen, “The Art of Computer Programming”, Erfinder von TEX
Künstliche Intelligenz, General Problem Solver
Automaten, Alg., Nichtdeterminismus, randomisierte Alg.
FORTRAN, Backus-Naur-Form Grammatik
formale Methoden zur Software Entwicklung
Programmiersprachen, APL
Programmiersprachen
Relationale Datenbanken
Komplexität, NP-Vollständigkeit
Betriebssystem UNIX
MODULA, PASCAL, Oberon
NP-Vollständigkeit
Algorithmen und Datenstrukturen (Lehrbuch)
Compilerbau, RISC-Computer
Computergraphik
Numerik, Floating Point Arithmetik
Time sharing
Logik, funktionale Progarmmierung: ML
PC-Entwicklung (Microsoft)
Komplexitätstheorie
Künstliche Intelligenz, prakt. Umsetzung
Komplexitätstheorie, Kryptographie
Temporallogik, Programmverifikation
Maus, Fenster
Datenbanktechniken
Rechnerarchitaktur, IBM 360
Zufallszahlen, Kryptographie
Simula, OOP
Public Key Kryptographie, RSA-Algorithmus
Objektorientierte Programmierung, Smalltalk
Vernetzung, TCP/IP
Design von Programmiersprachen (Algol 60), Compilerdesign
Parallele Programmierung, erste Frau mit Turing Preis!
Modellprüfung
Programmiersprachen und System Design
Frauen in der Informatik
Warum gibt es so wenige Frauen in der Informatik?1
•
Intelligenztests zeigen minimale Unterschiede ausschließlich bei:
◦
◦
•
Vorstellung räumlicher Drehungen von Figuren zugunsten der Männer
Sprachkompetenzen zugunsten der Frauen
Es gibt keine Intelligenz und Begabungsunterschiede die die geringe Beteiligung der Frauen erklären können!
Frauenanteil am Informatik-Studium (2001)
Land
England
Italien, Frankreich, Spanien, Portugal
frühere Sowjetunion
Bulgarien
Griechenland
Indien, Malaysia, Singapur
Deutschland
1
Frauenanteil [%]
35
40–50
50
60–70
59
50
8
teilweise entnommen aus Olga Goldmann Seminar: Geschichte der Informatik, www.virtosphere.de/
schillo/teaching/WS2001/Geschichts-Seminar.html
25
2.8.1
Frauen in der Geschichte der Informatik
Ada Augusta von Lovelace (1815-1852)
•
•
•
•
arbeitet mit Ch. Babbage an der Analytical Engine
Sie erfand Unterprogramme, Schleifen und bedingte Sprünge!
publizierte unter dem Kürzel A.A.L.
Mutter von vier Kindern
Grace Murray Hopper (1906-1992)
•
•
•
•
•
beteiligt an Entwicklung von Mark 1, Mark 2, Univac 1
entwickelt 1952 einen der ersten Compiler
“Debugging”: Eine tote Motte (bug) blockiert ein Relais im Rechner. Zitat: First actual case of a bug being found.
Zitat: Wenn du eine gute Idee hast, dann tu es einfach, denn es
ist viel einfacher sich hinterher zu entschuldigen, als vorher um
Genehmigung zu bitten.
Über 40 Ehrendoktorwürden und Preise
Bis etwa 1960 waren viele Frauen in der Informatik tätig:
•
•
2.9
Beim Knacken der Enigma in Bletchley Park (England)
Bei der Bedienung und Programmierung früher Rechner, u.a. Colossus (G.B.), Eniac
(USA), nach dem Krieg in Deutschland
Wichtige Institute und Firmen
IAS: Institute for advanced studies, Princeton, New Jersey, USA
MIT: Massachusettes Institute for Technology, Cambridge, Massachusetts, USA
SRI: Stanford Research Institute, Palo Alto, USA
Stanford University, Palo Alto, California, USA
Harvard University, Cambridge, Massachusetts, USA
UCB: Univ. of California, Berkeley, USA
AT&T Bell Labs: New Jersey, USA
26
Kapitel 3
Algorithmen und Datenstrukturen –
Einführung
In diesem Kapitel werden hauptsächlich Sortieralgorithmen untersucht. Ziel ist hier aber nicht
primär das Sortieren. Vielmehr wird hier an einem einfachen Beispiel die Entwicklung und
Verbesserung von Algorithmen und Datenstrukturen aufgezeigt. Wichtig ist auch die mathematische Analyse der Algorithmen bezüglich Rechenzeit und Speicherplatzverbrauch.
3.1
Sortieren durch Einfügen
Beispiel 3.1 7 4
4 7
4 7
3 4
3 4
1 3
8
8
8
7
5
4
3
3
3
8
7
5
5
5
5
5
8
7
1
1
1
1
1
8
Definition 3.1 Eine Liste A = (A1 , . . . , An ) heisst sortiert, wenn für alle
i = 1, . . . , n − 1 gilt Ai ≤ Ai+1 .
3.1.1
Algorithmus (grob)
Von links nach rechts: eine Zahl x wählen und verschieben nach links bis Ai−1 ≤ Ai = x ≤ Ai+1
erfüllt ist.
27
3.1.2
Algorithmus als C-Programm
Rechenzeit
void insertion sort(int a[], int n) {
int i, j, x;
/* Alle Elemente betrachten */
for (i = 1;
i < n;
i = i + 1) {
/* Tauschschleife */
x = a[i];
for (j = i - 1;
((x < a[j]) && (j >= 0));
j = j - 1) {
a[j + 1] = a[j];
}
a[j + 1] = x;
worst case
(Tmax (n))
M
n·C
n·I
best case
(Tmin (n))
M
n·C
n·I
(n − 1) · M
(n − 1) · (M + I)
Pn−1
(i + 1) · 2C
Pi=1
n−1
(i + 1) · (M + I)
Pi=1
n−1
i=1 i · (M + I)
(n − 1) · M
(n − 1) · (M + I)
(n − 1) · C
0
0
(n − 1) · (I + M )
(n − 1) · (I + M )
}
}
Durch kopieren von a(i) auf die Variable x und auf a(0) wird die Terminierung der Schleife
sichergestellt. Sollte die Zahl a(i) also kleiner als alle Elemente davor in der Liste sein und
ganz nach links verschoben werden müssen würde der Schleifenindex i ohne diese Terminierung
einen negativen Wert annehmen. Da die Liste aber bei a(0) aufhört, würde dies zu einem undefinierten Zustand führen. Diese Terminierung spart im Kopf der While-Schleife eine zusätzliche
Bedingung ein und reduziert somit den Aufwand proportional zu n.
3.1.3
Worst - Case Rechenzeit
Im Programmcode eingetragen ist für jede Programmzeile die Laufzeit. Als Parameter treten
rechnerabhängigen Größen I (Increment), M (Move) und C (Compare) auf:
I = Rechenzeit für eine Zähloperation
M = Rechenzeit für eine Zuweisungsoperation
C = Rechenzeit für eine Vergleichsoperation
Diese Zeiten sind konstant, d.h. nicht von n abhängig und deshalb für die Berechnung der
Komplexität unbedeutend. Für die Berechnung von exakten Laufzeiten sind sie jedoch sehr
wichtig.
28
Tmax (n) = (n − 1) · (I + C + 3M + I + M + I)
n
X
+
(i · C + (i − 1) · (2M + 2I))
i=2
= (3I + 4M + C) · n − (3I + 4M + C)
n
n
X
X
+C ·
i + 2(I + M ) ·
(i − 1)
i=2
mit
n
X
i=2
i=
i=2
n(n + 1)
n2 + n − 2
n2 n
−1=
=
+ −1
2
2
2
2
n
n−1
X
X
n(n − 1)
n2 n
(i − 1) =
i=
=
−
2
2
2
i=2
i=1
und
erhalten wir
a
b
{
c
z
}|
{
3
C
Tmax (n) = (I + M + ) ·n2 + (2I + 3M + C) ·n −(3I + 4M + 2C)
2
2
= a · n2 + b · n + c
}|
z
{
z
}|
Wenn die Konstanten nicht interessieren, kann die Berechnung der Worst-Case Rechenzeit
vereinfacht werden:
(n − 1) · (I + C)
(n − 1) · (3M + I)
n
X
i·C
→
→
→
(n − 1) · c1
(n − 1) · c2
n
X
(
i) · c3
i=2
i=2
..
.
..
.
..
.
Ergebnis: a · n2 + b · n + c
Bestimmung von a, b und c
1.) Messe drei Zeiten für verschiedene n = n1 , n2 , n3
−→ (n1 , T1 ), (n2 , T2 ), (n3 , T3 )
T(n)
T3
T2
T1
n1
n2
n3
29
n
2.) Einsetzen in Parabelgleichung:
T1 = a · n21 + b · n1 + c
T2 = a · n22 + b · n2 + c
T3 = a · n23 + b · n3 + c
3.) Auflösen des linearen Gleichungssystems nach a, b und c (siehe Übung 2).
Beispiel 3.2 Vergleich von 3 verschiedenen Komplexitäten
n
10
100
1000
Alg. 1
T (n) =
log n · c
1s
2s
3s
Alg. 2
T (n) = c · n
Alg. 3
T (n) = c · n2
Alg. 4
T (n) = c · n3
Alg. 5
T (n) = c · 2n
10 s
100 s
1000 s
100 s
10 000 s
1 000 000 s
1 000 s
1 000 000 s
1 000 000 000 s
1024 s
≈ 1030 s
≈ 10300 s
Die Werte wurden mit einem c von einer Sekunde errechnet. Eine bessere Hardware würde nur
dieses c verbessern und dadurch die Rechenzeit nicht wesentlich beeinflussen. Bei großen n ist
die Komplexität viel ausschlaggebender als die Konstante c.
3.1.4
Best-Case Rechenzeit
Ist die Liste A vorsortiert, so wird die Tauschschleife (innere for-Schleife) nicht durchlaufen und
das Programm ist viel schneller.
Analog zu den Berechnungen im Worst-Case kann man auch im Best-Case die Zeiten aus der
Tabelle aufaddieren und man erhält
Tmin (n) = d · n + e.
3.1.5
Einschub: Asymptotik (Landau-Symbole)
Beschreibung des asymptotischen Verhaltens von Rechenzeiten T (n) (oder Speicherplatz oder
anderer Funktionen) für n → ∞.
Idee: Vernachlässigung von konstanten Faktoren. Nur die Abhängigkeit von n für große n ist
wichtig.
Definition 3.2 Seien die Funktionen f : N → R+ , g : N → R+ gegeben - R+ = {x ∈ R|x ≥ 0}.
Dann schreibt man:
Asymptotische obere Schranke:
f ∈ O(g), wenn ∃ c > 0∃ n0 ∀ n > n0 : |f (n)| ≤ c · |g(n)|
f ∈ o(g),
wenn ∀ c > 0∃ n0 ∀ n > n0 : |f (n)| < c · |g(n)|
30
Asymptotische untere Schranke:
f ∈ Ω(g), wenn ∃ c > 0∃ n0 ∀ n > n0 : |f (n)| ≥ c · |g(n)|
f ∈ ω(g), wenn ∀ c > 0∃ n0 ∀ n > n0 : |f (n)| > c · |g(n)|
Asymptotische enge (harte) Schranke:
f ∈ Θ(g), wenn ∃ c0 > 0∃ c1 > 0∃ n0 ∀ n > n0 : c0 · |g(n)| ≤ |f (n)| ≤ c1 · |g(n)|
Bedeutung von O, o, ω, Ω, Θ:
f = O(g): f wächst höchstens so schnell wie g, kann aber gleich schnell wie g wachsen.
f = o(g): f wächst weniger schnell als g
f = Ω(g): f wächst mindestens so schnell wie g, kann aber gleich schnell wie g wachsen.
f = ω(g): f wächst schneller als g
f = Θ(g): f und g wachsen gleich schnell
O, Ω, Θ, o, ω sind Relationen auf Funktionen, wie z.B. <, ≤ auf reellen Zahlen.
Analogien:
Funktionen f : N → R+
f (n) = O(g(n))
f (n) = o(g(n))
f (n) = Ω(g(n))
f (n) = ω(g(n))
f (n) = Θ(g(n))
reelle Zahlen
a≤b
a<b
a≥b
a>b
a=b
Beispiele:
31
Symbolname
großes Omikron
kleines Omikron
großes Omega
kleines Omega
großes Theta
f (n) = 0.001 · n2
f (n) = n5
g(n) = 1000 · n
⇒ f = Ω(g) und f = ω(g)
g(n) = 0.001 · 5n ⇒ f = O(g) und f = o(g)
f (n) = 10 · n
g(n) = n ⇒ f = Θ(g)
Satz 3.1
T (n) = Θ(g(n))
⇔
T (n) = Ω(g(n)) und T (n) = O(g(n))
Die bisher berechneten Ergebnisse lassen sich nun also formulieren wie folgt:
32
Satz 3.2 Beim Sortieren durch Einfügen gilt
Tmin (n)
Tmax (n)
T (n)
T (n)
3.1.6
=
=
=
=
Θ(n)
Θ(n2 )
Ω(n)
O(n2 )
Schwachstellen und mögliche Verbesserungen
x
Die Suche nach der Einfügestelle für das Element x soll verbessert werden.
Suche in Listen
Aufgabe 1: Suche ein Element x in einer beliebigen Liste.
optimale Lösung: lineare Suche mit Tmax (n) = Θ(n)
Aufgabe 2: Suche ein Element x in einer sortierten Liste A[1 . . . n]
optimale Lösung: Bisektion
Der Bereich links von x ist bereits sortiert. Man findet die richtige Stelle für x indem man die
Liste links von x mehrfach halbiert.
Definition 3.3 bxc := max{y ∈ Z|y ≤ x}. bxc ist also die größte ganze Zahl kleiner oder
gleich x. Englisch: floor(x). Analog sei dxe = min{y ∈ Z|y ≥ x}. Englisch: ceiling(x)
Der Bisektionsalgorithmus
Bisektion(A,x)
a=1
b=n
m = b a+b
c
2
while A[m] 6= x & b > a
if x < A[m]
then b = m - 1
else a = m
m = b a+b
c
2
if A[m] == x
then print (”Hurra ”,x,”gefunden an Position ”,m)
else print (”Schade, ”,x,”nicht in A”)
33
Komplexität
Sei die Arraylänge n = 2k . Dann sind höchstens k Wiederholungen der While-Schleife erforderlich. Also ist die Rechenzeit proportional zu k, d.h. T (n) = c · k.
n = 2k
ln(n) = k · ln 2
ln n
k =
ln 2
Also gilt für die Bisektion
T (n) = c ·
ln n
= c · log2 n = O(lg n)
ln 2
Erläuterung: Alle Logarithmen unterscheiden lediglich um einen kostanten Faktor, wenn man
nur die Basis ändert.
Das Suchen der Einfügestelle ist mit logarithmischem Aufwand möglich.
Aber: verschieben der O(n) Arrayelemente im Array kostet linearen Aufwand.
Idee: verwende dynamische Datenstruktur als verkettete Liste.
x
Verschieben der Arrayelemente ist damit unnötig. x wird direkt an der richtigen Stelle eingefügt.
Aber: die Bisektion ist auf einer verketteten Liste nicht anwendbar.
Daher: für Sortieren durch Einfügen bleibt Tmax (n) = Θ(n2 )
3.2
Quicksort
Es soll die Liste 5, 3, 2, 6, 4, 1, 3, 7 sortiert werden. Dies erfolgt nach dem Prinzip divide and
conquer durch rekursiv wiederholtes Aufteilen und bearbeiten, wie in folgender Tabelle zu
sehen:
34
5
3
2
6
4
1
3
7
↑i
x = 5 (Pivotelement)
↑j
5
↑i
3
3
2
3
2
3
3
2
3
↑i
1
3 2
←→
3 2
↑i ↔↑j
2 3
3
↑j ↑i
2 3
3
↑i ↔↑j
2 3
3
↑j
↑i
2 3
3
↑i ↑j
2 3
3
1
1
↑i ↑j
1
1
1
6
4
←→
6
4
↑i ↔
1
4
↑j
1
4
↑j
3
4
1
3
↑j
5
7
4
1
↑j
6
5
↑i
6
5
↑i ↔↑j
5
6
↑j
↑i
5
6
↑i ↑j
5
6
4
5
6
7
4
5
6
7
4
5
6
7
4
7
7
7
x = 3, x = 6
7
7
7
Erläuterung: Der erste Wert der Liste ist das Pivotelement (ausgezeichnetes, besonderes Element). Zwei Indizes i und j durchlaufen die Liste nach folgendem Kriterium:
i sucht von links nach einem Wert ≥ x und j von rechts nach einem Wert ≤ x. Dann werden
Inhalt von i und von j vertauscht. Das setzt sich solange fort bis sich beide Indizes überkreuzen
oder gleich sind. Dann wird die Liste rechts von j geteilt und auf beiden Hälften rekursiv von
vorne begonnen.
3.2.1
Der Algorithmus
Seien A=Liste, p=Anfangsindex, r=Endeindex. Dann ist die rekursive Struktur gegeben durch:
Quicksort(A,p,r)
if p < r
then q=Partition (A,p,r)
Quicksort (A,p,q)
Quicksort (A,q+1,r)
Das Aufteilen erfolgt mittels
35
Partition(A,p,r)
x=A[p]
i=p-1
j=r+1
while TRUE do
repeat j=j-1
until A[j] ≤ x
repeat i=i+1
until A[i] ≥ x
if i < j
then vertausche A[i] mit A[j]
else Return(j)
Der erste Aufruf von Quicksort auf einer Liste A der Länge n erfolgt durch
Quicksort(A,1,n)
3.2.2
Analyse
Laufzeit von Partition
auf Array A[p...r] mit n = r − p + 1
T (n) = Θ(n)
Laufzeit von Quicksort im Best Case
n
n/2
n/2
n/4
2
1
n/4
2
1 ... 1
2
1 ... 1
n/4
2
1 ... 1
2
1 ... 1
n/4
2
1 ... 1
2
1 ... 1
log2 n Ebenen
2
1 ... 1
1
Rekursionsbaum
Der Rekursionsbaum hat n Blattknoten. Er wächst in der Breite exponentiell. Trotzdem ist die
Komplexität auf jeder Ebene Θ(n). Warum?
Zahl der Ebenen im Rekursionsbaum? Zur Vereinfachung nehmen wir an, das Array hat
n = 2k Elemente. Dann ist die Tiefe des Baumes gleich k. Auflösen nach der Tiefe k ergibt:
log2 n = log2 2k = k.
36
Die gesamte Rechenzeit ist also hier gleich der Produkt aus dem Aufwand pro Ebene und der
Zahl der Ebenen (Tiefe):
Tmin (n) = c · n · log2 n = Θ(n log n)
Laufzeit von Quicksort im Worst Case (sortierte Liste)
1
2
3
4
5
6
7
8
↑i
↑j
1
↑i ↑j
1
1
2
3
4
5
6
7
8
2
↑i ↑j
2
3
4
5 6
7
8
3
↑i ↑j
4
5
7
8
6
Aufwand pro Ebene:
n
n
n−1
1
n Ebenen
n
1
n−2
n−1
2
1
1
1
2
Rekursionsbaum
n
X
Tmax (n) = c2 · (
i + n)
i=2
n(n + 1)
− 1 + n)
2
n2 3
= c2 · ( + n − 1)
2
2
2
= Θ(n )
= c2 · (
Für die Rechenzeit T(n) gilt:
c1 · n log n ≤ T (n) ≤ c2 · n2
Idee zur Verhinderung des Worst Case: Liste vorher zufällig permutieren.
Begründung: Die Wahrscheinlichkeit für das Erzeugen einer sortierten Liste ist sehr klein. 101n
falls nur 10 Zahlen erlaubt sind.
Allgemeine Wahrscheinlichkeit: M1n für M unterschiedliche zu sortierende Werte und n verschiedene Zahlen in der Liste.
37
Beispiel 3.3 32 Bit Integer Zahlen: M = 232 , n = 106 ,
1
Mn
=
1
(232 )106
=
1
232·106
Folgerung: Die Wahrscheinlichkeit, dass ein randomisiertes Quicksort den Worst-Case trifft
ist sehr klein. Aber die zufällige Permutation der Liste vor dem Sortieren kostet Rechenzeit.
Daher:
Zufällige Wahl des Pivotelements
ersetze in Partition x = A[p] durch x = A[random (p,r)]
oder Ersetzung von Partition (A,p,r) durch:
Random-Partition(A,p,r)
i=Random (p,r)
vertausche A[p] mit A[i]
return Partition (A,p,r)
Random (p,r) liefert zufällig mit konstanter Wahrscheinlichkeit eine Zahl aus {p, p+1, . . . ,r}.
Bemerkung: Durch Randomisierung gibt es keine Eingabe mehr, für die der Algorithmus
immer Worst-Case Verhalten zeigt.
Average-Case-Analyse: Berechnung der mittleren Laufzeit des Algorithmus z.B. Quicksort
auf einer repräsentativen Menge von Eingaben.
Beispiel 3.4 Die Average-Case-Analyse für Quicksort ist sehr schwierig. Daher wird hier der
ungünstige Fall eines konstanten Aufteilungsverhältnisses 1 : m am Beispiel 1 : 9 behandelt.
n
9n/10
1n/10
81n/100
9n/100
9n/100
1n/100
729n 81n
1000 1000
81n
9n
1000 1000
81n
9n
1000 1000
9n
1n
1000 1000
9 dl
( 10
) ·n=1
1 dr
( 10
) ·n=1
9
+ log n = 0
10
log n
dl =
log 10
9
dl · log
T (n) <
Tiefe k =
log n
log 10
9
c
· n log n
log 10
9
≈ 21, 8 · log10 n
Aufwand auf jeder Ebene ≤ n ⇒
im Best-Case auch n · log n ist, gilt:
T (n) = O(n · log n). Da die Komplexität von Quicksort
38
Satz 3.3 Quicksort besitzt im Average-Case die Komplexität T (n) = Θ(n · log n)
3.3
Sortieren mit Bäumen (Heapsort)
Beispiel 3.5
1
16
i:
A[i] :
2
14
3
10
4
8
5
7
6
9
7
3
8
2
9
4
10
1
Darstellung von A als Baum:
16
14
8
2 8
4
4 9
1
2
10
7
5
9
3
6
3
7
1 10
Keine neue Datenstruktur nötig, sondern nur Funktionen parent, left, right mit den Eigenschaften
parent(i) = b 2i c
left(i) = 2i
right(i) = 2i + 1
(Vorgänger)
(linker Nachfolger)
(rechter Nachfolger)
Definition 3.4 Ein Array mit den Funktionen left, right, parent heisst Heap, wenn gilt
A[parent(i)] ≥ A[i]
Die Anzahl der Elemente in dem Array A bezeichnen wir mit length(A), die Anzahl der
Elemente in A, die einen Heap bilden, bezeichnen wir mit heapsize(A).
Definition 3.5 Die Höhe eines Knotens i in einem Baum ist gleich der Zahl der Kanten
im längsten Pfad von i zu einem Blattknoten. Die Höhe des Baumes ist gleich der Höhe des
Wurzelknotens.
Der folgende Algorithmus verwandelt einen Binärbaum in einen Heap unter der Voraussetzung,
dass beide Unterbäume schon Heaps sind.
39
Heapify(A,i)
vertausche A[i] mit seinem größten Nachfolger
A[largest] falls A[largest] > A[i]
Heapify (A,largest)
Beispiel 3.6
1
16 P
"" PPPP
"
2
4 bb
b
5
4
14
7 %
e
%8 e
9 10
2
8 1 3
10 %e
%6 e
7
9
3 1
16
P
"" PPPP
"
2
14 bb
b
4
5
4
7 %
e
%8 e
9 10
2
8 1 3
10 %e
%6 e
7
9
3 1
16
P
"" PPPP
"
2
14 bb
b
4
5
8
7 %
e
%8 e
9 10
2
4 1 3
10 %e
%6 e
7
9
3 Der Algorithmus
Heapify(A, i)
l = left(i)
r = right(i)
largest = i
if l ≤ length(A) AND A[l] > A[largest]
then largest = l
if r ≤ length(A) AND A[r] > A[largest]
then largest = r
if largest 6= i
then vertausche A[i] mit A[largest]
Heapify(A, largest)
Laufzeit von heapify
Vergleich von A[i] mit A[left(i)] und A[right(i)]: konstante Zeit= Θ(1)
Rekursion
Die maximale Zahl von Knoten in einem der Unterbäume geht für grosse n asymptotisch gegen
2
n, wenn n = Zahl der Unterknoten in i.
3
Rekurrenzrelation
2
T (n) ≤ T ( n) + Θ(1)
3
Das Auflösen der Rekurrenzrelation erfolgt mit Hilfe des Mastertheorems:
40
Satz 3.4 (Mastertheorem) Seien a ≥ 1, b > 1 Konstanten und f : R+ → R+ , T : R+ → R+
Funtionen mit
T (n) = aT (n/b) + f (n)
wobei n/b für die ganzzahlige Division (bn/bc
beschränkt werden durch


Θ(nlogb a )
falls






 Θ(nlogb a log n) falls
T (n) =




Θ(f (n))
falls




oder dn/be) steht. Dann kann T (n) asymptotisch
∃ε>0 : f (n) = O(nlogb a−ε )
f (n) = Θ(nlogb a )
∃ε>0 : f (n) = Ω(nlogb a+ε ) und
∃c<1 ∃n0 ∀n≥n0 : af (n/b) ≤ cf (n)
Für Heapsort gilt T (n) ≤ T ( 32 n) + Θ(1). Für den Worst Case gilt
n
+c
Tmax (n) = 1 · Tmax
3/2
Für die Anwendung des Mastertheorems gilt dann also a = 1, b = 32 , f (n) = Θ(1) sowie
nlogb a = n
log 3 1
2
=1
Es ist der zweite Fall anwendbar, denn f (n) = Θ(nlogb a ). Also gilt für heapify
Tmax (n) = Θ(1 · log n) = Θ(log n).
Beispiel 3.7 Anwendung des Master-Theorems auf Quicksort (Best Case):
T (n) = 2 T ( n2 ) + c · n
a = 2, b = 2, f (n) = c · n
nlogb a = nlog2 2 = n
f (n) = Θ(n)
⇒ 2. Fall: T (n) = Θ(n · log n)
Beispiel 3.8 wie oben, jedoch mit anderem f (n):
T (n) = 2T ( n2 ) + c · log n
a = 2, b = 2, f (n) = c · log n
nlogb a = n
f (n) = c · log n = O(n(1−ε) )
⇒ 1. Fall: T (n) = Θ(n)
3.3.1
Erzeugen eines Heap
Build-Heap(A)
length(A)
for i = b
c downto 1
2
do heapify(A,i)
41
Beispiel 3.9
1
4P
PPP
P
2
3
1
H
3 HH
e
e
H
4
5 6 7
2
16
9
10 %@@
%
8 9 10
14
8 7 1
4P
PPP
P
2
3
1
3 bb
e
b
e
4
5 6 7
14
16
9
10 %e
%8 e
9 10
2
8 7 1
4 "PPP
"
PP
" 2
3
16
10 bb
%e
b
7
5 %6 e
4
14 7 9 3 %e
%8 e
9 10
2 8 1 1
16
P
"" PPPP
" 2
3
14
10 bb
%e
b
4
7
5 %6 e
8 7 9 3 %e
%8 e
9 10
2 4 1 1
4 "PPP
"
PP
"2
3
1 10 bb
%e
b
% e
4
5 6 7
14 16 9 3 %e
%8 e
9 10
2
8 7 Analyse
obere Schranke
Jeder der Θ(n) Aufrufe von heapify kostet O(log n) Zeit. Also gilt
=⇒ T (n) = O(n log n).
bessere Schranke
Die Laufzeit von heapify hängt von der Höhe des Knotens im Baum ab. Die meisten Knoten
haben sehr niedrige Höhe!
(Zahl der Knoten auf Höhe h) ≤ d
n
e
2h+1
Die Laufzeit von heapify für Knoten der Höhe h wächst linear mit h. Also Theapif y (h) = O(h) =
O(log(Anzahl Knoten im Unterbaum))


blog nc l
blog nc
m
X
X
n
h
T (n) ≤
· O(h) = On
= O(2n) = O(n)
h+1
2
2h
h=1
h=1
Die vorletzte Gleichung gilt weil
∞
1
X
h
2
=
= 2,
h
2
(1 − 21 )2
h=1
was man in der Formelsammlung findet.
3.3.2
Der Heapsort - Algorithmus
Voraussetzung: Build-Heap setzt maximales Element an die Wurzel, d.h. in A[1]
42
Idee
Wiederhole folgende Schritte bis der Heap nur noch aus einem Element besteht:
1.) vertausche A[1] mit A[n]
2.) lösche A[n] aus dem Heap
3.) Heapify (A,1)
Beispiel 3.10
14
8
4
2 8
10
2
10
4
7
1 9
1
5
9
3
6
8
3
7
16 10
4
2 8
i
4
10 8
5
1
2
4
10 8
1
3
6
8
3
7
16 10
9
7
10 8
10 8
5
16 10
2
14 9
5
8
6
1
9
7
4
10 8
7
14 9
3
6
5
1
3
6
2
7
16 10
2
9
7
5
3
i
4
7
14 9
i
5
8
6
2
9
7
16 10
4
10 8
8
4
14 9
1
7
5
16 10
Analyse
Build-Heap: T (n) = O(n)
for-Schleife: (n − 1) mal Heapify mit T (n) = O(log n) und Vertauschen mit O(1)
T (n) ≤ c1 · n + (n − 1) · [c2 · log n + c3 ]
= c2 · n log n + (c1 + c3 ) · n − c2 log n − c3
|
{z
}
43
9
7
1
3
Heapsort(A)
Build-Heap(A)
for i= length(A) downto 2
do vertausche A[1] mit A[i]
heapsize(A)= heapsize(A)-1
Heapify(A,1)
= O(n log n)
6
2
Algorithmus
vernachlässigbar für n → ∞
3
16 10
i
3
1
2
1
3
7
1
10 8
2
4
14 9
3
16 10
2
8
4
3
4
i
4
3
2
1
2
1
1
7
1
4
1
i
4
i
6
2
4
14 9
3
16 10
3
i
5
7
3
2
14 9
7
1
2
4
9
i
8
7
9
2
4
14 9
1
8
6
3
9
7
3.3.3
Priority-Queues als Anwendung der Heap-Struktur
Bei der Verwaltung von Warteschlangen mit Aufträgen unterschiedlicher Priorität muß als
jeweils nächster Auftrag immer ein Auftrag mit höchster Priorität ausgewählt werden. Dies
kann zum Beispiel erreicht werden, indem man die Aufträge in einer sortierten Liste speichert.
Allerdings ist dann die Komplexität zum Speichern der Aufträge in der Liste linear in der Länge
n.
Verwendet man dagegen einen Heap zur Verwaltung der Warteschlangen von Aufträgen, so ist
die Komplexität zum speichern und holen von Aufträgen im Heap logarithmisch in n.
Einfügen eines Elements x im Heap
1.) neues Blatt erzeugen
2.) Pfad vom Blatt zur Wurzel durchsuchen und x an der richtigen Stelle einfügen.
Algorithmus
Heap-Insert(A, key)
heapsize(A) = heapsize(A)+1
i=heapsize(A)
while i>1 AND A[parent(i)] < key
do A[i] = A[parent(i)]
i=parent(i)
A[i]=key
Beispiel 3.11 Anwendung von Heap-Insert zum Einfügen des Elements X = 15
1
16
P
"" PPPP
"
2
3
14 10 bb
%e
b
4
5 %6 e
7
8
7
9
3 %
e
9 10
%8 e
2
4 1 1
16
XXX
XXX
""
"
X
2
3
14
10 b
%e
bb
% e
4
8 %
e
%8 e
9
2
4 1
16
X
XXX
""
XXX
"
2
X b
bb
4
5
8 14 %e
@
%8 e
9 10 @
11
2 4 1 7 5
7 @
@ 10 11
1
X 6
1
16
X
XXX
""
XXX
" 3
10 %e
7
%6 e
9 3 2
15 bb
b
4
5
8
14 %e
@
%8 e
9 10 @
11
2 4 1 7 Analyse
T (n) = O(log n).
44
7
9 3 3
10 %e
%6 e
7
9 3 3.4
Sortieren in linearer Zeit
Unter ganz bestimmten Bedingungen ist Sortieren sogar in linearer Zeit möglich, wie man an
folgendem Beispiel erkennt.
Idee
Wenn alle in der Liste A vorkommenden Sortierschlüssel aus einer bekannten endlichen Menge
sind, kann man durch einfaches Abzählen der Häufigkeiten aller in A vorkommenden Elemente
eine Tabelle S der Häufigkeiten erstellen. Danach wird die Liste A überschrieben mit den
Elementen in der richtigen Reihenfolge (siehe Beispiel).
Beispiel 3.12 Zu sortieren sei A = (2, 1, 4, 5, 4, 7, 3, 1, 4, 4, 1). Als Häufigkeitstabelle S erhält
man
Sortierschlüssel
Häufigkeit
1
3
2
1
3
1
4
4
5
1
6
0
7
1
Daraus erhält man einfach die sortierte Liste A = (1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 7).
Komplexität
Mit m = |S| entsteht beim Abzählen ein linearer Aufwand und beim Zurückschreiben auch und
man erhält
T (n) = c1 · n + c2 · m + c3 · n
= Θ(n + m)
Dieser Algorithmus ist besonders interessant, wenn die Zahl m der verwendeten Sortierschlüssel
klein ist, zum Beispiel beim Sortieren einer großen Adressdatei nach Postleitzahlen.
Das hier verwendete Verfahren setzt voraus, dass die Menge der verwendeten Schlüssel bekannt
ist. Daher ist der aufwändige Vergleichen der Sortierschlüssel nicht nötig. Ist diese Voraussetzung jedoch nicht erfüllt und auch sonst kein Zusatzwissen über die zu sortierenden Daten
vorhanden, so ist Sortieren in linearer Zeit nicht möglich und man kann für die Komplexität
folgende untere Schranke angeben:
Satz 3.5 Wenn ein Sortieralgorithmus für beliebige Listen nur mit Vergleichen und Kopieren
arbeitet und keine Zusatzinformation über die Liste erhält, dann gilt:
T (n) = Ω(n log n)
3.5
Hashing
Egal, welchen Suchbegriff man eingibt, moderne Suchmaschinen finden sehr schnell eine Antwort. Dies wird ermöglicht durch eine geeignete Datenstruktur, einen sogenannten Index. Eine
Möglichkeit, solch einen Index zu realisieren ist die Speicherung der Daten in einer Baumstruktur, wie wir sie bei der Verwaltung von priorisierten Warteschlangen in Form des Heap
kennengelernt haben.
45
Wir werden hier mit dem sogenannten Hashing ein Verfahren vorstellen, das im Mittel einen
Zugriff in konstanter Zeit erlaubt. Das heißt, die Zugriffszeit hängt nicht von der Datenmenge
ab.
Welche bekannte Datenstruktur erlaubt konstante Zugriffszeit?
3.5.1
Direkte Adressierung
Versuchen wir, für eine Suchmaschine einen Index unter Verwendung eines Array zu erzeugen.
Zuerst müssen die eingegebenen Strings auf numerische Schlüssel (natürliche Zahlen) abgebildet
werden. Bei einem erlaubten Alphabet mit 80 Zeichen (deutsche Klein-, Großbuchstaben, Ziffern
und 10 Sonderzeichen) werden diese nummeriert von 0 bis 79 und dann wird die Zeichenkette
z0 , . . . zl kodiert als Schlüssel
k = nl · 80l + nl−1 · 80l−1 + . . . + n1 · 80 + n0 · 1,
wobei ni die Nummer des i-ten Eingabezeichens ist. Wenn die Kleinbuchstaben die Nummern
0 bis 30 (inkl. Umlaute und ß) erhalten, würde zum Beispiel die Eingabe ,,hallo” kodiert als
o
l
l
a
h
14 · 804
+ 11 · 803 + 11 · 802 + 0 · 801 + 7 · 800 =
573440000 + 5632000 + 70400 +
0
+
7
= 579142407
Mit einer derartigen Nummer kann dann direkt ein Arrayelement angesprochen werden in der
Tabelle T in Abbildung 3.1.
Tabelle T
Schlüssel
Daten
0
1
Schlüsseluniversum
U
0
2
3
4
3
4
8
7
1
verw.
Schlüssel
K
1
2
5
6
5
5
6
7
6
9
8
9
7
Abbildung 3.1: Direkte Adressierung über Array T .
Wir beschränken die Strings als Eingabe für die Suchmaschine auf eine Länge von 20 Zeichen.
Wieviele unterschiedliche Eingaben sind hier möglich?
.....................................................................................................................................
Offenbar wird hierbei zu viel Speicherplatz benötigt.
46
3.5.2
Hash-Tabellen
Bei der direkten Adressierung muss die Tabelle Θ(|U |) Elemente haben, also gleich groß sein
wie das Schlüssel-Universum. Bei Verwendung einer sogenannten Hash-Tabelle kann viel Speicherplatz gespart werden. Die Größe der Tabelle reduziert sich Θ(|K|) Elemente, wobei K die
Menge der tatsächlich verwendeten Schlüssel ist.
Idee: Hash-Funktion bildet Schlüssel ab auf Indizes der Tabelle
Hash-Tabelle
h(k1 )
Schlüsseluniversum U
h(k4 )
verw.
Schlüssel
K
k1
h(k3 ) = h(k2 )
k4
k3
k2
Abbildung 3.2: Adressierung über Hash-Tabelle.
Definition 3.6 Eine Hashfunktion h bildet die Schlüssel des Universums ab auf eine (viel
kleinere) Menge {0, 1, . . . , m − 1} von Hash-Werten. Man nennt h(k) den Hash-Wert des
Schlüssels k.
Nachteil: Kollisionen sind nicht vermeidbar, s.o.: h(k3 ) = h(k2 ). Warum?
3.5.3
Hash-Funktionen
Eigenschaften von guten Hash-Funktionen:
•
Deterministisch. Warum?
•
Ähnliche Schlüssel werden nicht auf ähnliche Hash-Werte abgebildet
•
Möglichst wenige Kollisionen
•
Aber: Kollisionen sind möglich!
Modulo m:
h(k) = k mod m
Beispiel: k = 67, m = 16:
h(67) = 67 mod 16 = 3
Problem, wenn m = 2p : Dann berechnet h(k) die p niederwertigsten Bits von k.
Gute Wahl von m: Primzahlen nicht zu nahe bei einer Zweierpotenz
47
Die Multiplikationsmethode:
Zuerst wird k multipliziert mit einer Konstanten 0 < A < 1. Dann werden die Nachkommastellen des Ergebnisses mit m multipliziert. Von diesem Ergebnis wird dann der ganzzahlige Anteil
genommen:
h(k) = bm(kA mod 1)c
√
Laut [9] empfiehlt D. Knuth A = ( 5 − 1)/2 ≈ 0.61803.
Beispiel: k = 674301, A = 0.61803, m = 1000:
√
h(k) = b1000 · (674301 · ( 5 − 1)/2 mod 1)c = b1000 · (416740.93664804 mod 1)c
= b1000 · 0.93664804c = b936.64804c = 936
3.5.4
Kollisionsauflösung durch Verkettung
Hash-Tabelle
k1
Schlüsseluniversum U
verw.
Schlüssel
K
k1
k5
k4
k4
k5
k3
k2
k3
k2
Abbildung 3.3: Adressierung über Hash-Tabelle.
Analyse
Definition 3.7 Sei T eine Hash-Tabelle mit m Feldern, in der n Elemente gespeichert sind, so
wird α = n/m als Auslastung der Tabelle bezeichnet.
Wir nehmen im Folgenden an, dass die verwendete Hash-Funktion jeden vorkommenden Schlüssel
mit gleicher Wahrscheinlichkeit auf eines der Felder der Tabelle abbildet. Diese Annahme wird
als einfaches uniformes Hashing bezeichnet.
Satz 3.6 Werden in einer Hash-Tabelle die Kollisionen durch Verkettung aufgelöst, so kostet
eine Suche im Mittel Θ(1+α) Rechenzeit unter den Annahme des einfachen uniformen Hashing.
Wenn die Zahl der Felder der Hash-Tabelle proportional zur Zahl der zu speichernden Elemente
wächst, gilt n = O(m) und
α = n/m = O(m)/m = O(1).
Also folgt für die Zeit zum Suchen im Mittel Θ(1).
48
3.5.5
Offene Adressierung
Bei dieser alternativen Methode der Kollisionsauflösung werden alle Elemente direkt in der
Hash-Tabelle selbst gespeichert. Im Fall von Kollisionen wird ein neuer alternativer Index berechnet, und dies wird so lange wiederholt, bis eine freie Speicherzelle gefunden wird.
Diese Methode hat den Vorteil, dass keine Zeiger benötigt werden, was etwas Speicherplatz
spart. Allerdings kann es hier passieren, dass die Hash-Tabelle voll wird. α kann hier also nicht
größer als eins werden.
Als Literatur empfehle ich für dieses Kapitel [9].
49
Kapitel 4
Algorithmen auf Graphen
4.1
Einführung
Graphen werden immer dann verwendet, wenn man eine Menge von Objekten und Relationen
zwischen diesen Objekten darstellen und/oder untersuchen will. Verkehrsnetze werden z.B. oft
als Graph modelliert:
50
Bay
F
N
Ma
Ka
Reg
Ul
S
Pa
Li
M
Ros
Rv
Ba
Sal
Z
Be
Inn
Definition 4.1 Ein gerichteter Graph ist ein Paar G = (V, E), bestehend aus einer endlichen
Knotenmenge V (engl. vertex) und einer zweistelligen Relation E ⊆ V × V . Die Elemente von
E werden Kanten (engl. edge) genannt.
G0 = (V 0 , E 0 ) ist ein Teilgraph von G = (V, E), wenn V 0 ⊆ V und E 0 ⊆ E.
Beispiel 4.1 folgendes sind Graphen:
•
•
•
V1 = Menge aller Städte in Süddeutschland
E1 = {(x, y) ∈ V1 × V1 |es gibt eine direkte Straßenverbindung von x nach y}
V2 = Menge der Einwohner von Ravensburg
E2 = {(x, y) ∈ V2 × V2 |x kennt y}
V3 = Menge der Einwohner von Ravensburg
E3 = {(x, y) ∈ V3 × V3 |x ist verheiratet mit y}
G3 = (V3 , E3 ) ist Teilgraph von G2 = (V2 , E2 )
Zur graphischen Darstellung von Graphen werden Knoten durch Punkte und jede Kante (x, y)
durch einen Pfeil von x nach y dargestellt.
Beispiel 4.2
c
V = { a, b, c, d, e, f, g, h }
E = { (a, d), (d, a), (a, b),
(b, c), (c, a), (b, e),
(a, e), (f, g), (f, f ) }
f
a
h
b
d
e
g
Definition 4.2 Falls für jede Kante e = (x, y) ∈ E eines Graphen G = (V, E) auch die Kante
e0 = (y, x) ∈ E ist, so heißt G ungerichteter Graph. Alle anderen Graphen sind gerichtet.
Beim Zeichnen von ungerichteten Graphen wird für jedes verbundene Knotenpaar nur eine
Linie ohne Pfeile gezeichnet.
51
Beispiel 4.3 G = (V, E) mit V = Menge der Einwohner von Ravensburg,
E = {(x, y) ∈ V × V | x ist verheiratet mit y}
Definition 4.3
• Sei G = (V, E) ein Graph. Ein Pfad (oder Weg) von Knoten x ∈ V nach y ∈ V ist eine Folge
(x = a0 , . . . , a` = y) von Knoten mit (ai , ai+1 ) ∈ E. ` ist die Länge des Weges von x nach y.
• In einem einfachen Pfad kommt jeder Knoten höchstens einmal vor.
• Ein Pfad der Länge ` ≥ 1 von x nach x heißt Kreis.
• Ein Kreis, in dem außer dem Startknoten kein Knoten mehr als einmal vorkommt, heißt
Zyklus.
• Ein gerichteter Graph G = (V, E) heißt zyklenfrei oder gerichteter azyklischer Graph
(engl. directed acyclic graph (DAG)), wenn er keine Zyklen enthält.
• (x, x) und (x, y, x) heißen triviale Zyklen. Ein ungerichteter Graph ist zyklenfrei, wenn
es zwischen jedem Paar von Knoten (x, y) höchstens einen Pfad (ohne triviale Zyklen) gibt.
• Die Zahl der Kanten, die von einem Knoten v ausgehen oder in ihm enden heißt Grad des
Knotens. Er wird mit deg(v) bezeichnet. Bei ungerichteten Graphen wird jede Kante nur
einfach gezählt.
Beispiel 4.4 Für den Graphen aus Beispiel 4.2 gilt:
• (b, c, a, d, a) ist ein Pfad von b nach a.
• (c, a, b, e) ist ein einfacher Pfad von c nach e.
c
• (f, f, f, g) ist ein Pfad.
f
a
• Er enthält u.a. den Kreis (a, b, c, a, d, a).
• ({a, b, c, e}, {(a, b), (b, c), (b, e), (a, e)}) ist ein azyklischer Teilgraph von G.
h
b
• (a, b, c, a) und (a, d, a) und (f, f ) sind (bis auf Permutation) die einzigen Zyklen.
d
e
g
• deg(a) = 5, deg(b) = deg(f ) = 3, deg(h) = 0.
Definition 4.4
• Ein ungerichteter Graph G heißt zusammenhängend, wenn es zwischen je zwei beliebigen
Knoten einen Weg gibt.
• Ein zusammenhängender zyklenfreier Graph ist ein Baum.
• Eine Menge paarweise nicht zusammenhängender Bäume heißt Wald.
• Ein Kreis heißt Eulerkreis, wenn er jede Kante des Graphen genau einmal durchläuft.
4.2
Eulerkreise
Beispiel 4.5 Die Stadt Königsberg (heute Kaliningrad, Rußland) hatte folgenden Verlauf des
Flusses Pregel mit sieben Brücken. Leonhard Euler fragte sich 1736, ob es einen Rundweg durch
52
die Stadt gibt, auf dem jede Brücke genau einmal überquert wird. Der zugehörige Graph ist
rechts angegeben.
C
A
D
B
Bemerkung: Für Graphen mit Mehrfachkanten ist E statt einer Relation eine Multimenge
über V × V .
Satz 4.1 Ein ungerichteter zusammenhängender Graph enthält genau dann einen Eulerkreis
wenn der Grad jedes Knotens gerade ist.
Beweis: (Beweisskizze) “⇒”: Wird ein Knoten besucht, so über eine ankommende und eine
abgehende Kante. Bei jedem Besuch eines Knoten auf dem Eulerkreis werden also zwei Kanten
“verbraucht”.
“⇐”: Sei G ein Graph in dem alle n Knoten geraden Grad haben. Weil der Graph zusammenhängend ist, muss der Grad aller Knoten mindestens 2 sein. Dann besitzt der Graph also
mindestens n Kanten und damit einen Zyklus.
Nun konstruieren wir einen Eulerkreis mit folgendem Algorithmus: Wir starten bei einem Knoten und traversieren den Graphen so lange bis ein Knoten vorkommt, der schon besucht wurde.
Nun ist ein Kreis C gefunden. Alle Kanten von C werden nun gelöscht. Im verbleibenden Graphen wird dieses Verfahren fortgesetzt, bis alle Kanten besucht sind. Nun ist der Graph in
disjunkte Zyklen zerlegt. Diese lassen sich leicht zu einem Eulerkreis verbinden. Wir starten
auf einem beliebigen Zyklus und verfolgen diesen Zyklus, bis wir entweder wieder am Anfang
ankommen oder einen Knoten V finden, der auch in einem anderen Zyklus vorkommt. Wir verfolgen dann den zweiten Zyklus, bis wir wieder bei V angekommen sind oder bis wir wieder auf
einen Knoten W treffen, der zu einem weiteren Zyklus gehört. Dann folgen wir wieder diesem
Zyklus. Ein weiterer Zyklus darf nur dann betreten werde, wenn er vorher noch nicht betreten
war oder er über den Knoten wieder betreten wird, von dem man den Zyklus verlassen hat.
Dieses Verfahren wird solange fortgesetzt, bis alle Zyklen zu einem Eulerkreis verbunden sind
(siehe Abbildung).
2
53
Der im Beweis skizzierte Algorithmus (bekannt als Algorithmus von Hierholzer) arbeitet
in linearer Zeit. Das heißt, bei einem Graphen mit geradem Grad und m Knoten gilt für die
Rechenzeit T (m) = Θ(m).
4.3
Datenstrukturen für Graphen
4.3.1
Rv
Ul
M
S
Ka
Z
Ba
Be
F
Ma
N
Adjazenzmatrix
Rv Ul M S Ka Z Ba Be F Ma N
x x x
x x
x
x x
x
x x
x
x x
x
x x x
x
x
x
x
x x
x
x x
x
x x
x
x x
x x
x
x
x x x
x x
F
N
Ma
Ka
Ul
S
M
Rv
Ba
Z
Be
Die Matrix ist symmetrisch. Warum?
4.3.2
Adjazenzlisten
a
b
c
d
e 0
f
g 0
h 0
b
c
a 0
a 0
e
e 0
f
g 0
c
d 0
f
a
h
b
d
54
e
g
4.3.3
Liste von Adjazenzlisten
a
b
e
b
c
e 0
c
a 0
d
a 0
d 0
c
f
a
f
h
b
e 0
f
d
g 0
e
g
g 0
h 0
0
4.3.4
Vergleich der drei Datenstrukturen
Adjazenzmatrix
Adjazenzlisten
Liste von Adjazenzlisten
Vorteile
Berechnung der Inzidenz mit
O(1)
Speicherplatz = O(n + m)
Speicherplatz = O(n +
m), Knoten können einfach
gelöscht oder hinzugefügt
werden
Nachteile
Speicherplatz und Initialisierung teuer, beide O(n2 )
Berechnung der Inzidenz mit
O(m)
Berechnung der Inzidenz mit
O(n + m), Knotensuche mit
O(n)
n = Knotenzahl, m = Kantenzahl
Inzidenz bezeichnet eine Beziehung zwischen Knoten und Kanten in einem Graphen. Ein Knoten
heißt in einem Graph inzident mit einer Kante, wenn er von dieser Kante berührt wird, das
heißt, wenn diese ihn enthält.
4.4
Kürzeste Wege
Definition 4.5 Ein gewichteter Graph (auch bewerteter Graph) ist ein Tripel G =
(V, E, w), bestehend aus einem Graphen (V,E) zusammen mit einer Gewichtungsfunktion
w : E → R+ , die jeder Kante eine relle Zahl zuordnet. Die Länge eines Weges (x = a0 , . . . , a` )
ist
`−1
X
w(ai , ai+1 ).
i=0
55
Bemerkung: Setzt man bei nicht gewichteten Graphen alle Gewichte auf 1, so erhält man die
Weglänge gemäß Def. 4.3.
Beispiel 4.6 Entfernungstabelle einiger süddeutscher Städte
RV Ul M S Ka
Rv 0 86 178 195 –
Ul
0 123 107 –
M
0
–
–
S
0 64
Ka
0
Z
Ba
Be
F
Ma
N
Z
91
–
–
–
–
0
Ba Be F Ma
180 –
–
–
–
–
–
–
–
–
–
–
–
– 210 135
191 –
– 67
85 120 –
–
0 91 –
–
0
–
–
0 85
0
N
–
171
170
210
–
–
–
–
230
230
0
F
230
85
230
Ma
67 135
Ka
107
S
64
210
171
123
170
86
180
Be
Ul
195
191
Ba
N
210
85
91
120
Z
91
RV
178
M
Wegen der Symmetrie kann die untere Dreiecksmatrix weggelassen werden.
Definition 4.6 Ein Baum T = (V, E 0 ), der alle Knoten V eines Graphen G = (V, E) enthält,
heißt minimal aufspannender Baum, wenn die Summe aller Kantengewichte minimal ist,
d.h. wenn
X
E 0 = argminX⊂E
w(e).
e∈X
Bemerkung: argmin ist der x Wert einer Funktion f(x) an dem f(x) minimal ist.
4.4.1
Der Kruskal-Algorithmus
Satz 4.2 (Kruskal-Algorithmus) Für einen ungerichteten, zusammenhängenden, bewerteten Graphen findet der folgende Algorithmus einen minimal aufspannenden Baum T :
1. Setze T = {}
2. Sortiere die Kanten nach ihrem Gewicht.
3. Wähle aus den noch nicht gewählten Kanten die mit dem kleinsten Gewicht. Falls diese
Kante in T keinen Zyklus erzeugt, erweitere T um diese Kante. Wiederhole Schritt 3 bis
alle Kanten verbraucht sind.
Beispiel 4.7 Wir wenden nun den Kruskal-Algorithmus auf Beispiel 4.6 an und erhalten folgenden minimal aufspannenden Baum:
56
F
230
85
230
Ma
210
67 135
Ka
210
171
123
195
191
170
86
180
Be
Ul
107
S
64
Ba
N
85
91
120
Z
91
RV
178
M
Satz 4.3 Die Laufzeit des Kruskal-Algorithmus ohne den Schritt des Sortierens für einen Graphen mit n Knoten und m Kanten ist O(m + n log n). Mit optimierten Datenstrukturen ist
(ohne Sortieren) sogar eine fast lineare Komplexität erreichbar [9].
Definition 4.7 Gegeben sei ein bewerteter Graph G = (V, E, w).
• Beim Single Pair Shortest Path Problem (SPP) ist ein kürzester Weg von einem Knoten
a zu einem Knoten b gesucht.
• Beim Single Source Shortest Path Problem (SSP) sind kürzeste Wege von einem Knoten a zu allen anderen Knoten b ∈ V gesucht.
• Beim All Pairs Shortest Path Problem (APSP) ist für jedes Paar von Knoten (a, b) ein
kürzester Weg gesucht.
4.4.2
Der Dijkstra-Algorithmus
Wir geben nun einen bekannten Algorithmus für das SSP an:
Satz 4.4 (Dijkstra-Algorithmus) Für einen bewerteten Graphen G = (V, E, w) und einen
gegebenen Knoten a findet der folgende Algorithmus einen aufspannenden Baum, der das SSPProblem für den Knoten a löst. Hierbei ist
δ(S) = {k ∈ V \S|k ist mit einem Knoten aus S direkt verbunden.}
57
Dijkstra(G,a)
Setze S = {a}, F = {}
while S 6= V do
suche in δ(S) den Knoten v mit dem
kürzesten Pfad (a, . . . , u, v) von a zu v.
S = S ∪ {v}
F = F ∪ {(u, v)}
Beispiel 4.8 Dijkstra-Algorithmus mit a = Rv:
F
230
85
230
Ma
Ka
64
S
107
Be
91
Ul
Knoten in δ (S):
170
123
Kanten in F:
120
M
178
85
86
180
171
195
191
Ba
210
Knoten in S:
N
67 135 210
Z
91
RV = a
S
F
230
85
230
Ma
67 135
Ka
107
S
64
171
123
170
86
180
Be
Ul
210
195
191
Ba
N
210
85
91
120
Z
91
RV
178
M
Satz 4.5 Die Laufzeit des Dijkstra-Algorithmus O(m + Cn), wobei C eine Konstante ist, die
vom maximalen Kantengewicht abhängt [9].
4.4.3
•
Anwendungen
“Städteverbindungen” der Bahn
58
•
Routing im Internet: Router berechnet die beste Route zum nächsten Backbone-Knoten
über einen aufspannenden Baum, den er mit dem Dijkstra-Algorithmus erstellt.
Definition 4.8 Ein Hamilton-Kreis (hamiltonian circle) in einem Graphen G ist ein geschlossener Weg, in dem jeder Knoten aus G genau einmal vorkommt. Eine Clique in einem
(ungerichteten) Graphen ist ein vollvernetzter Teilgraph.
4.5
Das Problem des Handlungsreisenden
(traveling salesman problem, TSP)
gegeben: Menge von Städten s1 , . . . , sn und eine Entfernungstabelle w mit wij = |si − sj | =
Entfernung zwischen Stadt i und Stadt j.
gesucht: Eine Permutation (Vertauschung) Π von (s1 , . . . , sn ), so dass
n−1
X
wΠ(i),Π(i+1) + wΠ(n),Π(1)
i=1
minimal ist. Es ist also eine Route gesucht, die jede Stadt genau einmal besucht und am Ende
wieder im Ausgangspunkt endet.
Definition 4.9 Eine bijektive Abbildung einer endlichen Menge M auf sich selbst heißt Permutation.
Beispiel 4.9 Eine Permutation der Menge {1, . . . , 6}
i
Π(i)
4.5.1
1
4
2
2
3
1
Ein praktisches Ergebnis
TSP-Tour durch mehr als 15112 deutsche Städte:
59
4
3
5
5
6
6
David Applegate, Robert Bixby und William Cook von der Rice-Universität in Houston (Texas) sowie Vasek Chvatal von der
Rutgers-Universität in New Brunswick (New Jersey), 1998, siehe: www.tsp.gatech.edu
4.5.2
Der Nearest-Neighbour-Algorithmus
Idee
Starte in einem Knoten und wähle als nächsten immer den mit dem geringsten Abstand.
60
Algorithmus
NN TSP(w)
For i=1 To n Do
tour[i]=i
tour[n+1]=1
For i=2 To n-1 Do
next=argmin{w[i-1,j] | j ∈ tour[i...n]}
vertausche tour[i] mit tour[next]
Return(tour)
Komplexität
T (n) = Θ(n2 )
4.5.3
Der Greedy - Algorithmus
Idee
“Greedy” heißt auf deutsch “gierig”. Dieses Attribut trifft auf den Algorithmus sehr gut zu,
denn er greift gierig immer nach der “besten” Kante ohne auf das Gesamtresultat zu schauen.
In der Beschreibung des Algorithmus behandeln wir die Tour als Graph: Der Graph ”Tour”
wird jeweils um die Kante mit dem kleinsten Gewicht erweitert, wenn diese Kante eine Wegfortsetzung ist und keinen Kreis erzeugt.
Algorithmus
• sortiere alle Kanten in der Liste K nach ihrem Gewicht.
• Sei (v, v 0 ) die Kante aus K mit kleinstem Gewicht. Falls deg(v) < 2 und deg(v 0 ) < 2 und
(v, v 0 ) schließt keinen Zyklus mit < n Knoten, erweitere die Tour um (v, v 0 ) und lösche (v, v 0 )
aus K.
• Wiederhole 2. bis für alle v ∈ V deg(v) = 2.
Komplexität
T (n) = Θ(n2 log n)
4.5.4
Die Union-Find-Datenstruktur
Der oben beschriebene Algorithmus muss feststellen, ob in einem Graph ein Zyklus vorliegt
oder nicht, wenn man eine Kante zu diesem Graph hinzufügt. Die nachfolgend beschriebene
Union-Find Datenstruktur bietet eine effizente Methode, dies festzustellen.
Eine endliche Menge S sei in die disjunkten Klassen Xi partitioniert:
S = X0 ∪ X1 ∪ X2 ∪ . . . ∪ Xk
mit Xi ∩ Xj = Ø ∀i, j ∈ {0, 1, . . . , k}, i 6= j.
61
Zu jeder Klasse Xi wird ein Repräsentant ri ∈ Xi ausgewählt. Die zugehörige Union-FindStruktur unterstützt die folgenden Operationen effizient:
Init(S): Initialisiert die Struktur und bildet für jedes x ∈ S eine eigene Klasse mit x als
Repräsentant.
U nion(r, s): Vereinigt die beiden Klassen, die zu den beiden Repräsentanten r und s gehören,
und bestimmt r zum neuen Repräsentanten der neuen Klasse.
F ind(x): Bestimmt zu x ∈ S den eindeutigen Repräsentanten, zu dessen Klasse x gehört.
Implementierung
Eine einfache Implementierung speichert die Zugehörigkeiten zwischen den Elementen aus S
und den Repräsentanten ri in einer Liste. Für kürzere Laufzeiten werden jedoch in der Praxis
Mengen von Bäumen verwendet. Dabei werden die Repräsentanten in den Wurzeln der Bäume
gespeichert, die anderen Elemente der jeweiligen Klasse in den Knoten darunter.
U nion(r, s): Hängt die Wurzel des Baumes von s als neues Kind unter die Wurzel des Baumes
von r.
F ind(x): Wandert vom Knoten x aus den Pfad innerhalb des Baumes nach oben bis zur Wurzel
und gibt diese als Ergebnis zurück.
4.5.5
Heuristiken
Um die Operationen Find und Union zu beschleunigen, gibt es die zwei Heuristiken UnionBy-Size und Pfadkompression.
Union-By-Size
Bei der Operation U nion(r, s) wird der Baum, der kleiner ist, unter den größeren Baum gehängt.
Damit verhindert man, dass einzelne Teilbäume zu Listen entarten können wie bei der einfachen
Implementierung (r wird in jedem Fall Wurzel des neuen Teilbaums). Die Tiefe eines Teilbaums
T kann damit nicht größer als log |T | werden. Mit dieser Heuristik verringert sich die WorstCase-Laufzeit von F ind von O(n) auf O(log n). Für eine effiziente Implementierung führt man
bei jeder Wurzel die Anzahl der Elemente im Teilbaum mit.
Pfadkompression
Um spätere F ind(x) Suchvorgänge zu beschleunigen, versucht man die Wege vom besuchten
Knoten zur zugehörigen Wurzel zu verkürzen.
1. maximale Verkürzung (Wegkompression)
Nach dem Ausführen von F ind(x) werden alle Knoten auf dem Pfad von x zur Wurzel
direkt unter die Wurzel gesetzt. Dieses Verfahren bringt im Vergleich zu den beiden folgenden den größten Kostenvorteil für nachfolgende Aufrufe von F ind für einen Knoten
im gleichen Teilbaum. Zwar muss dabei jeder Knoten auf dem Pfad zwischen Wurzel und
x zweimal betrachtet werden, für die Laufzeit-Komplexität ist das jedoch unerheblich.
2. Aufteilungsmethode (splitting)
Während des Durchlaufes lässt man jeden Knoten auf seinen bisherigen Großvater zeigen
(falls vorhanden); damit wird ein durchlaufender Pfad in zwei der halben Länge zerlegt.
62
3. Halbierungsmethode (halving)
Während des Durchlaufes lässt man jeden zweiten Knoten auf seinen bisherigen Großvater
zeigen.
Diese Methoden haben beide dieselben Kosten wie die erste Kompressionsmethode (Knoten unter die Wurzel schreiben). Alle Kompressionsmethoden beschleunigen zukünftige
F ind(x)-Operationen.
Laufzeiten
Union-Find-Datenstrukturen ermöglichen die Ausführung der obigen Operationen mit den folgenden Zeitkomplexitäten (n = |S|):
Implementierung mit einer Liste L, worst-case: F ind: O(n), U nion: O(1)
Implementierung mit Bäumen:
• ohne Heuristiken: F ind: O(n), U nion: O(1)
• mit Union-By-Size, worst-case: F ind: O(log(n)), U nion: O(1)
• mit Union-By-Size, Pfadkompression, worst-case: F ind: O(log(n)), U nion: O(1)
• mit Union-By-Size, Pfadkompression, Folge von f F ind- und u U nion-Operationen:
O (u + (n + f ) · (log∗ (n)))
4.5.6
Test auf Zyklus
Zur effizienten Durchführung des Tests auf einen Zyklus baut man die Mengen Xi so auf, dass
zwei Knoten u und v eines Graphen genau dann in der selben Menge liegen, wenn es einen Weg
von u nach v gibt.
Bevor man nun eine Kante k = (u, v) zu einem Graphen hinzufügt, testet man, ob u und v
bereits durch den bisherigen Graphen verbunden sind (also ob F ind(u) = F ind(v) ist). Ist dies
der Fall, so würde man durch hinzufügen von k einen Zyklus erzeugen. Man kann k also nicht
hinzufügen. Ist dagegen F ind(u) 6= F ind(v), so kann man k hinzufügen und man vereinigt die
beiden, durch u und v identifizierten Mengen, zu einer neuen Menge U nion(u, v).
Beispiel 4.10 Vergleich von 2 Heuristiken mit der optimalen Lösung an einem ganz einfachen
Beispiel:
a
6
1
b
3
f
5
4
e
a
c
2
d
3
Greedy Algorithmus
b
f
4
2
e
1
6
a
5
c
b
f
e
c
d
d
Nearest Neighbour (Start in d)
Beispiel 4.11 Vergleich von 3 Heuristiken mit der optimalen Lösung:
63
optimale Tour
4.5.7
Optimaler Algorithmus Optimal TSP
Idee
berechne für jede Tour
Pn
i=1
wtour[i],tour[i+1] und wähle eine Tour mit minimalem Wert.
Komplexität
Ohne Beschränkung der Allgemeinheit ist die erste Stadt frei wählbar. Für die zweite Stadt
ergeben sich n − 1 Möglichkeiten, für die dritte n − 2 Möglichkeiten . . . Für die n-te Stadt: eine
Möglichkeit. Insgesamt sind dann also ·(n − 1)! Routen möglich.
Für jede Route muss dann noch deren Länge berechnet werden und am Ende die kürzeste
ermittelt werden, was bei naiver Implementierung einen zusätzlichen Faktor n zur Rechenzeit
liefert. Durch Speicherung der aktuellen Länge einer Tour kann dieser Faktor n aber auf einen
konstanten Faktor reduziert werden.
Also: T (n) = Θ · (n − 1)!
grobe Abschätzung:
n! ≤ n n . . . n = nn ,
(n − 1)! = (n − 1)(n − 2) . . . 1 ≤ (n − 1)n−1
damit ergibt sich
T (n) = O(nn−1 )
Eine bessere Abschätzung liefert die Stirling’sche Formel:
⇒
√
n
n! ≈ ( )n · 2Πn für n → ∞
e
√
n
T (n) = Θ(( )n−1 · n)
e
Man erhält hier also ein überexponentielles Wachstum.
64
Resultate
1.) Fachleute sind überzeugt, daß es keinen polynomiellen Alg. für TSP gibt!
2.) und dass es sogar für fast optimale Lösungen keinen polynomiellen Alg. gibt.
3.) für TSP mit Dreiecksungleichung ergibt die Minimum Spanning Tree Heuristik(siehe
nächsten Abschnitt) eine Tour die höchstens um den Faktor 2 länger ist als die optimale
Tour; die Minimum Spanning Tree Heuristik hat T (n) = O(n2 )
Dreiecksungleichung:
∀i, j, k wij ≤ wik + wkj
i
Diese Gleichung besagt, dass die direkte Verbindung zwischen zwei Städten immer minimale
Länge hat. Sie gilt zum Beispiel für Luftlinienverbindungen zwischen Städten. Für die Entfernungen auf Straßen gilt sie jedoch nicht immer.
j
dij
djk
d
ik
k
4.5.8
Wachstum der Rechenzeit von Optimal TSP
Folgende Tabelle veranschaulicht das extrem schnelle Wachstum der Rechenzeit von Optimal TSP. Heute ist das TSP-Problem mit optimierten Algorithmen für etwa 30 Städte lösbar.
Wie man an der Tabelle erkennt, ist der Aufwand für 40 Städte etwa um den Faktor 1016 höher
und damit also unerreichbar.
n
10
20
30
40
50
4.5.9
(n-1)!
362880
121645100408832000
8841761993739701954543616000000
20397882081197443358640281739902897356800000000
608281864034267560872252163321295376887552831379210240000000000
(n-1)!
3.6 · 105
1.2 · 1017
8.8 · 1030
2.0 · 1046
6.1 · 1062
Die Minimum-Spanning-Tree-Heuristik
Definition 4.10 Ein Preorder-Tree-Walk traversiert einen Baum folgendermassen: Beginnend mit dem Wurzelknoten werden von links nach rechts rekursiv alle Nachfolgerknoten besucht.
Beispiel 4.12
65
Listet man nun alle besuchten Städte in der
Angewendet auf den minimal aufspannenden besuchten Reihenfolge und löscht alle WiederBaum mit Wurzelknoten Bern ergibt sich:
holungen so ergibt sich ein einfacher Pfad, der
alle Knoten besucht.
F
230
Ma
107
S
64
210
230
85
230
Ma
Ka
170
123
85
91
120
Z
91
178
RV
107
S
64
85
91
Be
210
171
123
170
86
180
Ba
Ul
195
191
M
N
210
67 135
171
86
180
Be
Ul
195
191
Ba
N
210
67 135
Ka
F
230
85
120
Z
RV
91
178
M
Im Fall eines voll vernetzten Graphen läßt sich dieser Pfad durch eine Verbindung von Frankfurt
nach Bern zu einem Hamilton-Kreis schließen und man erhält eine Näherungslösung für das
TSP-Problem. Dieses heuristische Vorgehen nennt man die Minumum-Spanning-TreeHeuristik.
Ist der Graph nicht vollständig vernetzt, wie im Beispiel, so ist es durchaus möglich, dass es
keinen Hamilton-Kreis gibt.
Der minimal aufspannende Baum liefert jedoch auch hier einen guten Ausgangspunkt für eine
Näherung zur Lösung des TSP-Problems.
F
230
85
230
Ma
210
67 135
Ka
107
S
64
4.6
210
171
123
170
86
180
Be
Ul
195
191
Ba
N
85
91
120
Z
91
RV
178
M
Planare Graphen
Definition 4.11 Läßt sich ein Graph in der Ebene darstellen, ohne dass sich Kanten kreuzen,
so nennt man ihn planar. Die Menge der durch die Kanten begrenzten Flächenstücke wird mit
A bezeichnet.
Beispiel 4.13 Zwei planare Darstellungen des vollständigen Graphen mit vier Knoten:
66
Für diesen Graphen gilt |A| = 4.
Satz 4.6 (Eulerformel) Für jeden planaren zusammenhängenden Graphen G = (V, E) gilt
|V | − |E| + |A| = 2.
Beweis: Falls G ein Baum ist gilt |V | = |E| + 1 und |A| = 1 und es ergibt sich
|V | − |E| + |A| = |E| + 1 − |E| + 1 = 2.
Für den Fall, dass G kein Baum ist zeigen wir die Behauptung per Induktion über die Zahl der
Kanten n = |E|. Für n = 0 besteht der Baum aus einem Knoten, d.h. es gilt |V | = 1, |E| = 0,
|A| = 1 und die Formel stimmt.
Wir nehmen an, die Formel gilt für n ≥ 0. Nun fügen wir eine Kante hinzu und erzeugen den
neuen Graphen G0 = (V 0 , E 0 ) mit |V 0 | = |V | und |E 0 | = |E| + 1. Die neue Kante schließt einen
Kreis und es gilt |A0 | = |A| + 1, woraus
|V 0 | − |E 0 | + |A0 | = |V | − (|E| + 1) + |A| + 1 = |V | − |E| + |A| = 2
2
folgt.
67
Kapitel 5
Formale Sprachen und Endliche
Automaten
5.1
Grundlagen
Man muss sich Sprachen vorstellen wie einen Legobaukasten. Die Buchstaben des Alphabets
entsprechen elementaren Bausteinen und die Worte, beziehungsweise Sätze entsprechen gebauten Objekten. Solche Mengen lassen sich mehr oder weniger einfach beschreiben. Zum Beispiel
die Menge der Objekte, die nur aus roten Steinen gebaut sind. Oder die Menge der Objekte bei
denen auf einem Basisstein nur Steine oben draufgesetzt werden dürfen, aber nicht daneben.
Was ist, wenn ich das fertige Objekt auf den Kopf stelle? Muß dann die Forderung immer noch
erfüllt sein?
Um solche Unklarheiten auszuschließen, werden wir bei den Sprachen ganz formal vorgehen. Wir
werden Spielgregeln in Form von Grammatiken zum Aufbau von Sprachen angeben. Mit diesen
Spielregeln können dann nur noch Worte aus einer bestimmten Sprache erzeugt (abgeleitet)
werden.
Hier stellen sich sofort einige für den Informatiker sehr wichtige und interessante Fragen:
• Läßt sich jede formale Sprache durch eine Grammatik beschreiben?
• Wenn ich eine Grammatik G habe, die eine Sprache L definiert, wie kann ich erkennen,
ob ein Wort zu dieser Sprache gehört oder nicht?
• Etwas konkreter: Ist es möglich, für eine konkrete Programmiersprache L in endlicher
Zeit zu entscheiden, ob ein vorgegebener Text ein Programm dieser Sprache darstellt
oder nicht. Diese Aufgabe ist der Syntaxcheck des Compliers.
• Ist diese Entscheidung vielleicht sogar effizient möglich, das heißt, auch für große Programme in kurzer Zeit?
• Wenn ja, wie macht man das?
• Kann man vielleicht sogar automatisch Fehler in Programmen erkennen, wie zum Beispiel
Endlosschleifen?
• Kann man überprüfen, ob ein Programm korrekt ist?
Die Beantwortung dieser Fragen ist Bestandteil des Gebiets der formalen Sprachen und Automaten. In dieser sehr knappen Einführung werden wir aber nur auf ganz einfache (reguläre)
Sprachen und auf die endlichen Automaten, das einfachste Maschinenmodell, eingehen können.
Eine ausführlichere Darstellung findet sich z.B. in [?].
68
Definition 5.1 Ein Alphabet Σ ist eine endliche nicht leere Menge von Zeichen.
Definition 5.2 Die Menge Σ∗ aller Worte ist wie folgt rekursiv definiert.
• Σ ⊂ Σ∗ und auch das leere Wort ε ist in Σ∗ enthalten.
• Für jedes Wort w ∈ Σ∗ und jedes Zeichen x ∈ Σ ist auch wx ∈ Σ∗ . wx ist die Zeichenkette,
die entsteht, wenn man das Zeichen x an das Wort w anhängt.
Jede Teilmenge von Σ∗ wird Sprache genannt.
Sprachen sind noch einfacher als Lego-Baukästen. Es gibt genau vier Möglichkeiten, zwei Alphabetzeichen a und b miteinander zu verknüpfen, nämlich aa, ab, ba, oder bb. Diese Verknüpfung
heißt Konkatenation und ist nicht vertauschbar. Damit kann man beliebig lange endliche Worte
bauen, ähnlich wie beim Lego-Baukasten.
Beispiel 5.1
Σ = {0, 1}
Σ∗ = {0, 1, ε, 00, 01, 10, 11, 001, 000, 011, 010, . . .}
Beispiel 5.2
Σ
Σ∗
T erme
T erme
=
=
=
⊂
{+, −, ·, /, (, ), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, x, y, a, b}
{. . . , ) + − · 567ax, . . .}
{x, y, a, b, (a), a + b, (a − 4) · y, . . .}
Σ∗
Die Menge aller korrekten arithmetischen Terme ist eine kleine Teilmenge von Σ∗ . Ein Affe,
der zufällig auf einer entsprechenden Tastatur tippt würde viele Versuche benötigen, um einen
korrekten Term zu erzeugen.
Definition 5.3
• Sei w ∈ Σ∗ und n ∈ N0 . Dann ist wn das durch n-fache Wiederholung von w entstandene
Wort. w0 ist also das leere Wort ε.
• Für eine endliche Zeichenmenge M ist M ∗ die Menge aller Zeichenketten die aus Elementen
in M gebildet werden können. Das leere Wort gehört zu M ∗ dazu. Die Menge M + = M ∗ \ε
enthält dagegen nur Worte mit mindestens einem Zeichen.
69
Beispiel 5.3 Sei Σ = {a, b, c}. Dann sind
∅,
{aa, ab, aaa},
{an |n ∈ N0 } = {ε, a, aa, aaa, aaaa, . . .},
{(ab)n |n ∈ N0 } = {ε, ab, abab, ababab, abababab, . . .},
{an bn |n ∈ N0 } = {ε, ab, aabb, aaabbb, aaaabbbb, . . .}
Teilmengen von Σ∗ und somit Sprachen über dem Alphabet Σ.
5.2
Grammatiken
Besonders interessant sind strukturierte Sprachen. Eine Sammlung von zufällig erzeugten Wörtern
ist für die meisten Anwendungen nicht sehr hilfreich. “Struktur” heißt hier, dass sich die Sprache
endlich beschreiben läßt. Wir werden Grammatiken verwenden um Sprachen zu beschreiben.
Aus dem Sprachunterricht in der Schule ist die Grammatik der deutschen Sprache bekannt.
Ein Satz der deutschen Sprache kann zum Beispiel bestehen aus < Subjekt > < Prädikat >
< Objekt > und < Subjekt > wiederum kann ersetzt werden durch < Artikel >< Substantiv >.
Damit ist also Die Studentin spielt Schach ein wohlgeformter Satz entsprechend der einfachen
angegebenen Grammatik. Jede Programmiersprache besitzt eine Grammatik.
Beispiel 5.4 Die Menge der arithmetischen Terme wie zum Beispiel x · (x + a · (b − 12)) läßt
sich durch folgende Regelgrammatik charakterisieren:
< Term >
< Term >
< Term >
< Term >
< Term >
< Term >
< Term >
< Var >
< Konst >
< Zahl >
< Ziffer >
→
→
→
→
→
→
→
→
→
→
→
< Term > + < Term >
< Term > − < Term >
< Term > / < Term >
< Term > · < Term >
(< Term >)
< Var >
< Konst >
x|y
a|b| < Zahl >
< Zahl >< Ziffer > | < Ziffer >
0|1|2|3|4|5|6|7|8|9
Hier steht das Zeichen | für “oder”, das heißt, eine Regel S → u|v steht für die zwei Regeln
S → u und S → v. Durch sukzessives Anwenden einer der Regeln aus P beginnend mit dem
Startsymbol kann man den obigen Term x · (x + a · (b − 12)) ableiten:
< Term >
⇒ < Term > · < Term >
⇒ < Var > · < Term >
⇒ x· < Term >
⇒ x · (< Term >)
⇒ x · (< Term > + < Term >)
⇒ x · (< Var > + < Term >)
⇒ x · (x+ < Term >)
⇒ x · (x+ < Term > · < Term >)
⇒ x · (x+ < Konst > · < Term >)
⇒ x · (x + a· < Term >)
⇒ x · (x + a · (< Term >))
⇒ x · (x + a · (< Term > − < Term >))
⇒ x · (x + a · (< Konst > − < Term >)) ⇒ x · (x + a · (b− < Term >))
⇒ x · (x + a · (b− < Konst >))
⇒ x · (x + a · (b− < Zahl >))
⇒ x · (x + a · (b− < Zahl >< Ziffer >)) ⇒ x · (x + a · (b− < Ziffer >< Ziffer >))
⇒ x · (x + a · (b − 1 < Ziffer >))
⇒ x · (x + a · (b − 12))
70
Definition 5.4 Eine Grammatik ist ein 4-Tupel
G = (V, Σ, P, S)
mit
• V als endliche nichtleere Menge der Variablen.
• Σ als Menge der Konstanten oder Terminalalphabet und V ∩ Σ = ∅.
• P ⊂ (V ∪ Σ)+ × (V ∪ Σ)∗ als endliche Menge der Produktionsregeln.
• S ∈ V ist die Startvariable.
Definition 5.5 Die in Beispiel 5.4 und im Folgenden verwendete Art der Darstellung von
Grammatikregeln wird nach ihren Erfindern Backus-Naur-Form (BNF) genannt.
Beispiel 5.5 Mit
G = ( {< Term >, < Var >, < Konst >, < Zahl >, < Ziffer >},
{x, y, a, b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, (, ), +, −, ·, /},
P, < Term >)
und P als Menge der Regeln aus Beispiel 5.4 ergibt sich also eine Grammatik mit den angegebenen Variablen, Konstanten und < Term > als Startsymbol.
Eine äquivalente Darstellung von Regelgrammatiken in grafischer Form bieten die Syntaxdiagramme, die wir hier nicht formal einführen. Ein Beispiel soll genügen:
Beispiel 5.6 Syntaxdiagramm für Terme
Var:
Term:
Term
+
Term
x
Term
_
Term
y
Term
/
Term
Term
*
Term
a
(
Term
)
b
Konst:
Zahl
Var
Konst
Zahl:
Ziffer:
Ziffer
0
1
2
71
3
4
5
6
7
8
9
Definition 5.6 Eine Folge von Wörtern (w0 , w1 , . . . , wn ) mit w0 = S und wn ∈ Σ∗ heißt
Ableitung von wn , falls für i ≥ 1 jedes der Wörter wi aus wi−1 entstanden ist durch Anwendung
einer Regel aus P auf ein Teilwort von wi−1 . Für einen Teilschritt schreibt man wi−1 ⇒ wi . Ist
ein Wort w durch einen oder mehrere Teilschritte aus u ableitbar, so schreibt man u ⇒∗ w.
Obige Grammatik erzeugt die (unendliche) Menge der Terme als Teilmenge von Σ∗ . Allgemein
definiert man
Definition 5.7 Die durch G erzeugte Sprache L(G) ist die Menge aller Worte aus Σ∗ ,
die aus G ableitbar sind, d.h.
L(G) = {w ∈ Σ∗ | S ⇒∗ w}.
Formale Sprachen werden eingeteilt in verschiedene Klassen, die sogenannte Chomsky-Hierarchie.
Wir werden uns im Folgenden mit regulären Sprachen beschaftigen.
Definition 5.8 Eine Sprache heißt regulär, wenn alle Regeln die Form A → a, A → aB oder
A → ε besitzen, d.h. auf der linken Seite der Regeln steht immer eine Variable und auf der
rechten Seite steht entweder ein Terminalsymbol oder ein Terminalsymbol gefolgt von einer
Variablen.
Beispiel 5.7 Die Sprache {an bm |n ∈ N, m ∈ N} ist regulär und läßt sich durch die Grammatik
G = ({S, T }, {a, b}, P, S) beschreiben mit
P = { S → aS, S → aT, T → bT, T → b }.
Beispiel 5.8
Σ = {a, b}
G1 = ({S}, Σ, P, S)
P = { S → aS, S → bS, S → ε }
Offenbar läßt sich aus dieser Grammatik jedes Wort w ∈ Σ∗ ableiten, also gilt L(G1 ) = Σ∗ .
5.3
Reguläre Ausdrücke
Reguläre Ausdrücke dienen wie reguläre Grammatiken der Beschreibung von regulären Sprachen (Typ-3-Sprachen nach der Chomsky-Hierarchie).
72
Definition 5.9 Reguläre Ausdrücke zum Alphabet Σ sind:
1.) ∅ = {}
2.) ε
3.) a, falls a ∈ Σ
4.) sind α, β reguläre Ausdrücke, so auch αβ, α|β und α∗
hierbei steht α|β für α oder β, α∗ für beliebig viele Wiederholungen von α (auch 0 Wiederholungen).
Beispiel 5.9 aa∗bb∗ beschreibt {an bm /n ∈ N, m ∈ N}. Für aa∗ schreibt man kürzer a+ . Der
Operator + steht also für beliebig viele Wiederholungen, aber mindestens eine.
Beispiel 5.10 Sei Σ = {., 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.
0.(0|1|2|3|4|5|6|7|8|9)+
beschreibt die Menge aller Dezimalzahlen mit 0 vor dem Dezimalpunkt.
Noch einfacher geht es, wenn man zur Beschreibung von Zeichenmengen folgende vereinfachende
Notationen einführt:
[xyz]
Kurzform von (x|y|z)
.
steht für jedes (beliebige) Zeichen
\x
steht für das Zeichen x, auch wenn x ein Sonderzeichen (z.B. ,,.”) ist
a{n, m} Ausdruck a mit n bis m Wiederholungen
a?
a{0,1}
a+
a{1, ∞}
a∗
a{0, ∞}
[ˆa]
jedes Zeichen außer a
[ˆa − k] jedes Zeichen außer a bis k
Nun lassen sich die Dezimalzahlen einfacher beschreiben mit
0\.[0123456789]+
oder noch einfacher durch
0\.[0 − 9]+
0 − 9 steht hier für den Zeichenbereich von 0 bis 9.
Die Syntax von Email-Adressen lässt sich durch den Ausdruck
................................................................................................................................. beschreiben.
Satz 5.1 Jede reguläre Sprache ist durch einen regulären Ausdruck beschreibbar. Umgekehrt
definiert jeder reguläre Ausdruck eine reguläre Sprache.
73
Im Gebiet der formalen Sprachen werden Sprachen, die mächtiger sind als die regulären Sprachen, behandelt. Zum Erkennen dieser Sprachen reichen aber endliche Automaten nicht mehr
aus. Hier werden mächtigere Maschinenmodelle, wie zum Beispiel Kellerautomaten und Turingmaschinen benötigt.
5.4
Endliche Automaten zur Worterkennung
Ein einfaches Modell ist der endliche Automat. Anschaulich ist ein endlicher Automat ein
Rechenelement, welches auf einem Eingabeband beginnend mit dem ersten Zeichen der Eingabe
das eingegebene Wort Zeichen für Zeichen liest. In jedem diskreten Rechenschritt macht der
Automat einen Zustandsübergang. Abhängig vom aktuellen Zustand und dem gelesenen Zeichen
geht der Automat in einen neuen Zustand über. Die Zahl der Zustände ist endlich. Erreicht der
Automat nach Lesen des letzten Zeichens einen Endzustand, so hat er das Wort erkannt.
Lesekopf
HAL LO
Z
Zustand
Beispiel 5.11 Der durch folgende Regeln beschriebene Automat akzeptiert alle Zeichenketten
(Worte) bestehend aus einer beliebigen Anzahl a-s gefolgt von einer beliebigen Anzahl b-s,
mindestens jedoch ein a und ein b. Die Regelmenge des Automaten mit den Zuständen S, T
und dem Endzustand e ist
δ = {S, a → S; S, a → T ; T, b → T ; T, b → e}
Die Zustandsübergangsrelation δ läßt sich übersichtlich durch die
Zustandsübergangstabelle
darstellen:
T
e
δ S
a {S, T }
b
{T, e}
Man beachte, dass die Zustandsübergangsrelation δ nicht eindeutig ist, denn zum Beispiel kann
der Automat nach Lesen eines a im Zustand S nach S oder nach T übergehen. Dies zeichnet
den nichtdeterministischen Automaten aus.
Besonders anschaulich ist der zugehörige Zustandsgraph:
a
S
b
a
T
b
e
Der beschriebene Automat kann nur passiv Eingaben akzeptieren oder abweisen. Er löst also
ein binäres Entscheidungsproblem. Man kann solch einen Automaten einfach erweitern durch
eine Ausgabefunktion.
74
5.5
Automaten mit Ausgabe
Beispiel 5.12 Es soll ein Getränkeautomat mit Hilfe eines endlichen Automaten programmiert
werden. Der Automat kann mit bis zu 4 Dosen Mineralwasser gefüllt werden. Wenn eine 1-EuroMünze eingegeben wird, soll er eine Dose Wasser ausgeben. Bei Eingabe einer anderen Münze
soll er die eingegebene Münze wieder ausgeben, aber kein Getränk. Wenn der Automat leer ist
soll er anhalten und per Funk den Service benachrichtigen.
Ein endlicher Automaten (mit Ausgabe) für diese Aufgabe ist gegeben durch folgende Tabelle
mit den Zuständen z0 , z1 , z2 , z3 , z4 und den erlaubten Eingabezeichen e, f, m. Im Zustand zi
enthält der Automat i Flaschen Mineralwasser. e steht für die Eingabe/Ausgabe eines Euro,
f für Eingabe einer falschen Münze. m steht für eine Flasche Mineralwasser. m kann sowohl
eingegeben werden (durch den Betreiber) als auch ausgegeben werden (an den Kunden). Ein
Paar x, y in der Tabelle beschreibt den Nachfolgezustand x und das Ausgabezeichen y.
z0
m z1 , ε
e z0 , e
f z0 , f
z1
z2 , ε
z0 , m
z1 , f
z2
z3 , ε
z1 , m
z2 , f
z3
z4
z4 , ε
z2 , m z3 , m
z3 , f z4 , f
Das Zustandsdiagramm zu diesem Automaten sieht so aus:
f
z0
f
m
e
z1
f
m
e
z2
f
m
e
z3
f
m
e
z4
e
Dieser Automat akzeptiert alle Eingabesequenzen (Worte), die zum leeren Automaten (d.h. zu
z0 ) führen.
5.6
Formale Beschreibung von Automaten
Genau wie bei allen Programmiersprachen wird auch für endliche Automaten eine streng formale Beschreibung benötigt. Diese ist aber auch noch für theoretische Überlegungen in der
Theorie der formalen Sprachen notwendig ( ⇒ Theoretische Informatik, Master).
Formal wird der Automat wie folgt definiert:
Definition 5.10 Ein endlicher Automat M besteht aus einem 5-, bzw. 7-Tupel
M = (Z, Σ, δ, z0 , E)
bzw.
M = (Z, Σ, δ, z0 , E, γ, Θ)
75
mit
Z
Σ
δ
z0
E
γ
Θ
:
:
:
:
:
:
:
endliche Zustandsmenge
endliches Eingabealphabet, Σ ∩ Z = φ
Z × Σ → P(Z), die Zustandsübergangsfunktion
Startzustand
Menge der Endzustände
Z × Σ → Θ, die Ausgabefunktion
Ausgabealphabet
Definition 5.11 Ein Wort w = w1 . . . wn mit wi ∈ Σ wird akzeptiert von dem endlichen
Automaten M genau dann wenn M gestartet im Startzustand auf w1 nach n Anwendungen
der Funktion δ, d.h. nach Lesen von wn , einen Endzustand z ∈ E erreichen kann.
Die von M akzeptierte (erkannte) Sprache L(M ) ist
L(M ) = {w ∈ Σ∗ | M akzeptiert w}
Beispiel 5.13 Der Automat aus Beispiel 5.11 wird beschrieben durch das 5-Tupel
M = ({S, T, e}, {a, b}, δ, S, {e})
mit
δ = {S, a → S; S, a → T ; T, b → T ; T, b → e}.
Beispiel 5.14 Der Getränkeautomat aus Beispiel 5.12 wird beschrieben durch das 7-Tupel
({z0 , z1 , z2 , z3 , z4 }, {e, f, m}, δ, z0 , {z0 }, γ, {e, f, m})
wobei δ und γ gegeben sind durch die angegebene Automatentabelle.
Definition 5.12 Beim nichtdeterministischen endlichen Automaten (NFA) sind (im Gegensatz
zum deterministischen endlichen Automaten (DFA)) für jeden Zustand Z und Eingabezeichen
a mehrere Regeln
z, a → z1
..
.
z, a → zn
erlaubt.
Gibt es eine möglichst einfache und effiziente Rechenmaschine, mit der man für ein beliebiges
Wort w entscheiden kann, ob dieses zu einer vorgegebenen regulären Sprache gehört?
76
Definition 5.13 Die Aufgabe, zu entscheiden, ob ein Wort w zu einer Sprache L gehört, heißt
Wortproblem.
Grammatik
erzeugt
erkennt
←−
−→
Sprache
Automat
Das Wortproblem für reguläre Sprachen kann durch endliche Automaten effizient gelöst
werden.
Beispiel 5.15 An der Sprache L = {an bm |n ∈ N, m ∈ N} erkennt man schön, wie die Regelgrammatik in einfacher Weise in einen nichtdeterministischen Automaten übersetzt werden
kann:
Automat
δ = {S, a →
S, a →
T, b →
T, b →
Regelgrammatik
P = {S → aS
S → aT
T → bT
T → b}
S
T
T
e}
Es gibt auch einen deterministischen Automaten, der die Sprache erkennt (siehe Aufgabe 39).
Satz 5.2 NFAs und DFAs sind gleich mächtig, d.h. zu jedem NFA gibt es einen DFA, der die
gleiche Sprache erkennt.
Satz 5.3 Eine Sprache L wird von einem endlichen Automaten genau dann erkannt, wenn sie
regulär ist.
77
Kapitel 6
Zusatzmaterial
6.1
Logarithmen
Die folgenden Schreibweisen sind üblich:
lg Logarithmus zur Basis 10
ln Logarithmus zur Basis e (natürlicher Logarithmus)
logb Logarithmus zur Basis b
6.1.1
Beispiele
lg(100) = 2
lg(1000) = 3
lg(10000) = 4
lg(n) = lg(n)
⇔
⇔
⇔
⇔
102 = 100
103 = 1000
104 = 10000
10lg(n) = n
log2 (8) = 3 ⇔ 23 = 8
log2 (16) = 4 ⇔ 24 = 16
log2 (23 ) = 3 ⇔ 23 = 8
6.1.2
(6.1)
(6.2)
(6.3)
(6.4)
(6.5)
(6.6)
(6.7)
Logarithmen - Regeln
Umrechnung Logarithmen verschiedener Basen:
logb (x) = y ⇔ by = x
loga (x) = z ⇔ az = x
logb (a) = logb (a) ⇔ blogb (a) = a
blogb (a)∗z = x
logb (x) = logb (a) ∗ loga (x)
(6.8)
(6.9)
(6.10)
(6.11)
(6.12)
Ableitung der Logarithmusfunktion
ln(x)0 =
78
1
x
(6.13)
6.2
Anwendung des Mastertheorems
1. Bestimme a und b
a Anzahl der tatsächlich ausgeführten rekursiven Aufrufe innerhalb der Prozedur. Bei
graphischer Darstellung: Anzahl der Verzweigungen des Rekursionsbaumes.
b Zahl, durch die n geteilt wird bei dem rekursiven Aufruf. Falls z.B. n halbiert wird,
ergibt sich b = 2.
2. Bestimmen der Funktion nlogb (a) . Beispiel b = 2, a = 4 ergibt n2 , da 22 = 4.
3. Vergleich der Funktion f (n) aus der Rekurenzgleichung mit der gerade bestimmten Funktion nlogb (a) . (f bestimmt die Komplexität der Prozedur für den nicht rekurrenten Fall.):
• Ist f (n) weniger stark steigend als nlogb (a) , so ist Fall 1 des Mastertheorems anzuwenden;
• ist f (n) gleich steigend wie nlogb (a) , so ist Fall 2 des Mastertheorems anzuwenden
und
• ist f (n) stärker steigend als nlogb (a) , so ist Fall 3 des Mastertheorems anzuwenden.
79
Kapitel 7
Übungen
7.1
Zahlensysteme
Aufgabe 1 Wählen Sie zufällig eine Zahl zwischen 32 und 64. Geben Sie diese Zahl in Hex-Form
einschließlich Rechenweg an!
7.2
7.2.1
Sortieren
Sortieren durch Einfügen
Aufgabe 2
a) Programmieren Sie “Sortieren durch Einfügen” in C für Integerzahlen - Arrays.
b) Testen Sie das Programm mit sortierten, zufälligen und umgekehrt sortierten Arrays auf
Korrektheit.
c) Bestimmen Sie für sortierte, zufällige und umgekehrt sortierte Arrays die Parameter a, b
und c von T (n) = a · n2 + b · n + c. Da in der Sprache C die Länge statischer Arrays auf
250000 beschränkt ist, sollten Sie mit dynamischen Arrays arbeiten. Z.B.:
int* a; /* Verweis auf ein Array */
n = 300000000; /* Größe des Arrays */
a = (int*) malloc(sizeof(int)*n); /* Speicherplatz reservieren */
/* Initialisierung, sortieren, Ausgabe */
free(a); /* Speicherplatz freigeben */
d) Bestimmen Sie die theoretische Rechenzeit für ein Array der Länge 5 · 109 .
e) Warum wird in der Praxis T (5 · 109 ) viel größer sein als oben errechneter Wert?
f ) Durch welche Maßnahme kann man die berechnete Rechenzeit tatsächlich erreichen?
Aufgabe 3 Ordnen Sie folgende Funktionen nach Ihrem asymptotischen Wachstum (log ist
der Zehnerlogarithmus, ln der natürlich Logarithmus):
√
√
n
n!
log n
(ln n)ln n n3/2 n log n (n + 1)! n2n ln n
2n
ln ln n
nn
(ln n!) n2/3 ( 32 )n log n
n
80
ln 2n
Aufgabe 4 Kreuzen Sie in folgender Tabelle alle zutreffenden Felder an. Es seien k ≥ 1, > 0
und c > 1. Es stehen die Abkürzungen O, o, Ω, ω und Θ für f (n) = O(g(n)), etc. Vergleichen
Sie hierzu das asymptotische Verhalten der Funktionen f und g. Zeichnen Sie ggf. die Graphen
der beiden Funktionen.
f (n) g(n)
nk
cn
log n
n
2n
2n/2
nlog m mlog n
n!
nn
√
n nsin n
O
o Ω ω Θ
Aufgabe 5 Beweisen Sie Satz 3.1, d.h. T (n) = Θ(g(n))
O(g(n)).
7.2.2
⇔
T (n) = Ω(g(n)) und T (n) =
Quicksort
Aufgabe 6 Skizzieren Sie den Rekursionsbaum von Quicksort für ein konstantes Aufteilungsverhältnis von 1:k und leiten Sie aus diesem Baum T (n) = O(n lg n) ab.
Aufgabe 7 Programmieren Sie Quicksort für einfache Arrays von Integer-Zahlen, indem Sie die
Funktion Partition wie in der Vorlesung beschrieben implementieren. Zeigen Sie empirisch,
dass für zufällig sortierte Arrays Trand (n) = Θ(n lg n) und für vorsortierte Arrays Tmax (n) =
Θ(n2 ) gilt.
Aufgabe 8 Beweisen Sie, dass für Sortieralgorithmen Tmin (n) = Ω(n) gilt.
Aufgabe 9
Gegeben sei folgender Programmteil eines C-Programms:
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
for(k = 1; k <= j; k++)
z = z+1;
a) Berechnen Sie die Laufzeit T (n) und geben Sie die (asymptotische) Zeitkomplexität an.
b) Welchen Wert hat z nach Verlassen der äußersten Schleife für n = 100?
Aufgabe 10 Gegeben sei die rekursive Funktion fib:
fib(0) = 1
fib(1) = 1
fib(n) = fib(n − 1) + fib(n − 2) für n ≥ 2.
81
a) Berechnen Sie fib(5).
b) Zeichnen Sie den Rekursionsbaum für fib.
c) Bestimmen Sie anhand des Rekursionsbaumes die Komplexität von fib.
7.2.3
Heapsort
Aufgabe 11 Warum wird der Schleifenindex i in Zeile 2 von Build-Heap von blength[A]/2c
bis 1 erniedrigt und nicht von 1 bis blength[A]/2c erhöht?
Aufgabe 12 Stellen Sie den Ablauf von Build-Heap für A = (5, 3, 17, 10, 84, 19, 6, 22, 9)
grafisch dar, ähnlich wie in Beispiel 3.9.
Aufgabe 13 Stellen Sie den Ablauf von Heapsort für A = (5, 13, 2, 25, 7, 17, 20, 8, 4) grafisch
dar, ähnlich wie in Beispiel 3.10.
Aufgabe 14 Benutzen Sie die Master-Methode zur Berechnung der Laufzeit der Suche durch
Bisektion mit der Rekurrenzgleichung T (n) = T (n/2) + Θ(1).
Aufgabe 15 Geben Sie mit Hilfe des Master-Theorems asymptotische Schranken für folgende
Rekurrenzen an:
a)
T (n) = 4T (n/2) + n
b)
T (n) = 4T (n/2) + n2
c)
T (n) = 4T (n/2) + n3 .
7.2.4
Hashing
Aufgabe 16 Überlegen Sie sich eine Hashfunktion h(x) für Strings. Jedes Wort soll hierbei auf
einen Hashwert abgebildet werden. Implementieren Sie diese in eine Programmiersprache ihrer
Wahl und wenden Sie das Programm auf einen beliebigen Text an.
Tipp: Als Basis für die Schlüssel bieten sich die ASCII-Werte der Buchstaben an.
Aufgabe 17 Verwenden Sie je einmal die modulare Hash-Funktion und einmal die Multiplikationsmethode, um Schlüssel k = 1, 2, 3, ...39 auf eine Hash-Tabelle mit Verkettungsmöglichkeit
und 13 Behälter (Buckets) zu verteilen. Achten Sie dabei darauf, dass jedes Wort nur einmal
je Hash-Funktion betrachtet wird!
Aufgabe 18 Bestimmen Sie anhand der Ergebnisse der vorhergehenden Aufgabe, welche der
beiden Hash-Funktionen das einfache uniforme Hashing eher erfüllt.
82
7.3
Graphen
Aufgabe 19 Ist jeder zyklenfreie, ungerichtete Graph ein Wald? Begründen Sie!
Aufgabe 20 Zeigen Sie, dass in jedem Graphen G = (V, E) mit m Kanten
X
deg(v) = 2m
v∈V
gilt.
Aufgabe 21 Konstruieren Sie für den Graphen aus dem Beweis von Satz 4.1 einen Eulerkreis,
indem Sie mit anderen Zyklen beginnen.
Aufgabe 22 Geben Sie für den bewerteten Süddeutschlandgraphen die Adjazenzlisten und die
Liste von Adjazenzlisten an.
Aufgabe 23 Geben Sie für den Graphen aus Beispiel 4.2 Adjazenzmatrix an.
Aufgabe 24 Erzeugen Sie einen minimal aufspannenden Baum mit dem Algorithmus von
Kruskal für den SFBay-Graphen:
Aufgabe 25 Verwenden Sie den Algorithmus von Dijkstra für das Single-Source-Shortest-PathProblem beim SFBay-Graphen mit Start in Palo Alto.
Aufgabe 26 Gegeben ist folgende Entfernungstabelle deutscher Städte:
83
Br
Aachen
Basel
Berlin
Bremen
Dortmund
Dresden
Düsseldorf
545
650
370
155
645
90
Aachen
Do
875
775
555
745
550
Basel
Be
400
495
200
560
Berlin
Aa
235
490
285
Bremen
515
70
Dortmund
Dü
Dre
580
Dresden
Ba
a) Bestimmen Sie mit dem Nearest-Neighbour-Algorithmus eine (heuristische) Lösung für
das TSP-Problem. Starten Sie in Düsseldorf. Geben Sie die Tour sowie deren Länge an.
b) Bestimmen Sie einen Minimum Spanning Tree mit dem Kruskal-Algorithmus. Zeichnen
Sie diesen in die Landkarte (unten) ein.
c) Verwenden Sie die Minimum-Spanning-Tree-Heuristik mit Wurzelknoten Bremen zur Bestimmung einer Lösung des TSP-Problems. Zeichnen Sie die Lösung in die Karte ein und
geben Sie Tour sowie Länge an.
Aufgabe 27 Versuchen Sie, die Minimum-Spanning-Tree-Heuristik zur Lösung des TSP-Problems
beim SFBay-Graphen anzuwenden. Vergleichen Sie das Ergebnis mit dem des Greedy-Algorithmus
bei Start in San Franzisko oder anderen Städten. Warum treten hier Probleme auf?
Aufgabe 28 Bestimmen Sie eine optimale Tour für das TSP-Problem beim SFBay-Graphen.
Aufgabe 29 Für einen planaren (ebenen) ungerichteten Graphen sei A die Menge der durch
die Kanten des Graphen begrenzten Flächenstücke. Überprüfen Sie an allen bisher verwendeten
Graphen (V, E) die Gültigkeit der Euler-Formel
|V | − |E| + |A| = 2.
Aufgabe 30 Es soll ein Programm entworfen werden, das bei gegebener Abstandsmatrix für
vollständig vernetzte Graphen eine optimale Tour findet.
a) Schreiben Sie ein Programm für Optimal TSP mit 4 Städten
b) Schreiben Sie ein Programm für Optimal TSP mit n Städten
7.4
Formale Sprachen und Endliche Automaten
Aufgabe 31
a) Geben sie eine Grammatik an, die alle Zeichenketten der Form
ab, abab, ababab, . . . erzeugt.
b) Geben sie einen regulären Ausdruck an, der alle Zeichenketten der Form
ab, abab, ababab, . . . erzeugt.
84
Aufgabe 32 Geben Sie eine Grammatik an für die Sprache L = {ai bj ck | i ∈ N, j ∈ N, k ∈ N}
Aufgabe 33 Geben Sie reguläre Ausdrücke an für
a) groß geschriebene Worte wie z.B. Hallo, aber nicht HALLO.
b) groß geschriebene Worte mit mindestens 3 und höchstens 5 Buchstaben.
c) Gleitpunktzahlen mit beliebig vielen Stellen vor dem Komma und mindestens einer Stelle
nach dem Komma.
Aufgabe 34 Geben Sie für jede der in Aufgabe 33 angegebenen Sprachen einen endlichen
Automaten an, der diese erkennt.
Aufgabe 35
Beschreiben Sie die durch folgende regulären Ausdrücke definierten Sprachen und geben Sie
Beispiele an.
a) \\(index|color|label|ref)\{[^\}]*\}
b) %.*
c) \\section\*?\{.*\}
d) [A-Za-z0-9]+@[A-Za-z0-9]+(\.[A-Za-z0-9]+){1,6}
Aufgabe 36
konstruieren sie (deterministische oder nichtdeterministische) endliche Automaten für folgende
durch reguläre Ausdrücke gegebenen Sprachen:
a) [0-9]*\.[0-9]+
b) \\section\*?\{.*\}
Aufgabe 37 Es soll eine Fußgängerampel mit Hilfe eines endlichen Automaten programmiert
werden. Die Ampel hat die zwei Zustände rot und grün (aus der Sicht des Fahrzeugs). Im
Zustand rot akzeptiert die Ampel Signale von der Kontaktschleife auf der Straße und schaltet
dann auf Grün. Im Zustand Grün akzeptiert die Ampel Signale vom Fußgängertaster und
schaltet auf Rot. Alle anderen Eingaben ignoriert der Automat.
a) Geben Sie einen endlichen Automaten für diese Aufgabe an.
b) Zeichnen Sie ein Zustandsdiagramm zu diesem Automaten.
Aufgabe 38 Es soll ein Getränkeautomat mit Hilfe eines endlichen Automaten programmiert
werden. Der Automat kann mit bis zu 4 Dosen Mineralwasser, 4 Dosen Limo und 4 Dosen
Bier gefüllt werden. Wenn eine 1-Euro-Münze eingegeben wird, soll er eine Dose des gewählten
Getränks ausgeben. Bei Eingabe einer anderen Münze soll er die eingegebene Münze wieder
ausgeben, aber kein Getränk. Wenn von einer Getränkesorte alle Dosen ausgegeben sind, soll
er anhalten und per Funk den Service benachrichtigen.
a) Geben Sie einen endlichen Automaten (mit Ausgabe) für diese Aufgabe an.
85
b) Zeichnen Sie ein Zustandsdiagramm zu diesem Automaten.
c) Geben Sie einen regulären Ausdruck für diese Sprache an.
d) Geben Sie eine reguläre Grammatik an, welche die für diesen Automaten erlaubte Eingabesprache akzeptiert.
Aufgabe 39 Konstruieren Sie einen deterministischen endliche Automaten, der zu dem aus
Beispiel 5.15 äquivalent ist.
86
Literaturverzeichnis
[1] Wikipedia – Die freie Enzyklopädie. www.wikipedia.org. 2.7
[2] F. Naumann. Vom Abakus zum Internet. Wissenschaftliche Buchgesellschaft, 2001. Geschichte der Informatik. 2.1
[3] H. Matis. Die Wundermaschine. mitp-Verlag, 2002. Geschichte des Computers. 2.1
[4] W. de Beauclair. Rechnen mit Maschinen – eine Bildgeschichte der Rechentechnik. Vieweg
Verlag, 1968. Die Lektüre dieses Bilderbuches lohnt sich! 2.1
[5] D. Shasha and C. Lazere. Out of Their Minds: The Lives and Discoveries of 15 Great
Computer Scientists. Copernicus/ An Imprint of Springer-Verlag, 1995. Sehr unterhaltsam
und informativ.
[6] V. Claus and A. Schwill. Duden Informatik. Bibliographisches Institut & F.A. Brockhaus
AG, 1988. Ein gutes Nachschlagewerk zur Informatik allgemein.
[7] P. Rechenberg and G. Pomberger. Informatik-Handbuch. Hanser Verlag, 2001.
[8] C. Horn and O. Kerner. Lehr- und Übungsbuch Informatik, Band 1: Grundlagen und
Überblick. Fachbuchverlag Leipzig, 2001.
[9] T.H. Cormen, Ch.E. Leiserson, and R. L. Rivest. Introduction to Algorithms. MIT Press,
Cambridge, Mass, 1994. Sehr gute Einführung in die Analyse von Algorithmen. 3.5.3,
3.5.5, 4.3, 4.5
[10] N. Wirth. Algorithmen und Datenstrukturen. Teubner-Verlag, Stuttgart, 1983 (3. Auflage).
Ein Klassiker, vom Erfinder der Sprache PASCAL.
[11] R. Sedgewick. Algorithmen. Addison-Wesley, Bonn, 1995. Übersetzung d. engl. Originals,
empfehlenswert.
[12] P. Tittmann. Graphentheorie. Fachbuchverlag Leipzig, 2003. Sehr gutes Buch mit vielen
Beispielen. Leider fehlen die Wegesuchalgorithmen.
[13] S. Krumke and H. Noltemeier. Graphentheoretische Konzepte und Algorithmen. Teubner
Verlag, 2005. Exakt und gleichzeitig anschaulich.
[14] Paul E. Black (Ed.). Dictionary of Algorithms and Data Structures [online]. National
Institute of Standards and Technology, 2004. http://www.nist.gov/dads.
[15] S. Skiena. The Algorithm Design Manual. Springer Verlag, 1997. Gutes Buch mit vielen
Algorithmen für den Praktiker.
87
Herunterladen