Beuth Hochschule Stichworte zu Algorithmen SS15, S. 1 Stichworte

Transcription

Beuth Hochschule Stichworte zu Algorithmen SS15, S. 1 Stichworte
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 1
Stichworte zu Algorithmen
Stichworte und allgemeine Informationen zur Lehrveranstaltung
Algorithmen (MB2-ALG) für den Zug 1
im Studiengang Medieninformatik Bachelor (MD-B)
im Sommersemester 2015 bei Ulrich Grude.
Anmerkung: Die parallele Veranstaltung für den Zug 2 wird von Prof. Böhler betreut.
In dieser Datei finden Sie u.a. die Termine und Orte der einzelnen seminaristischen Unterrichte (SUs)
und Übungen (Üs), die Regeln, nach denen man für diese LV Noten bekommt und weitere Informationen. Im Laufe des Semesters können Sie in dieser Datei nach jedem SU ein paar Stichworte zum Inhalt
des Unterrichts (und manchmal auch Korrekturen und Ergänzungen etc.) finden.
Einleitung
1. Diese Lehrveranstaltung (LV) stellt ziemlich hohe Ansprüche an ihre TeilnehmerInnen. Das liegt unter
anderem daran, dass sie (die LV, seit dem SS13) schon im 2. Semester stattfindet und Sie (die TeilnehmerInnen der LV) vorher nur ein Semester Programmierung hatten.
2. Kommen Sie zu allen Vorlesungen und Übungen. Betrachten Sie das Verpassen einer Vorlesung oder
einer Übung nicht als eine Option, sondern als eine kleine Katastrophe, die aufwendiges Nachholen erforderlich macht.
3. Wenn Sie das Gefühl bekommen sollten, in den Vorlesungen oder Übungen nicht genug zu lernen,
dann geben Sie nicht gleich auf. Überlegen Sie, was Sie anders machen könnten, um mehr zu lernen, und
was ich (als Betreuer dieser LV) anders machen sollte. Über Verbesserungsvorschläge können wir immer
reden (vorzugsweise vor oder nach dem Unterricht).
Einige Unterlagen zu dieser LV finden Sie (ziemlich weit oben) auf meiner Netzseite
http://public.beuth-hochschule.de/~grude/
Außerdem brauchen Sie Zugriff auf das Buch "Java ist eine Sprache" von Ulrich Grude. Sie können es
kostenlos in der Bibliothek der Beuth Hochschule ausleihen (oder für viel Geld in einem Buchladen kaufen). Einige Abschnitte in diesem Buch sind für diese LV Algorithmen wichtig.
S. 2, SS15
Stichworte zu Algorithmen
Beuth-Hochschule
Termine und Orte
Erster Termin Zug 1 und Zug 2: Mittwoch 08.04.2015, 10.00 Uhr, Raum DE36/1
(Verteilung von Studierenden, die nicht im 2. Semester sind, auf die Züge 1 und 2)
Erster Termin Zug 1: Donnerstag 09.04.2015, 08.00 Uhr, Raum D212
Für den Zug 1 sind drei Übungsgruppen geplant: 1a, 1b und 1c. Es folgen hier die Termine und Orte aller seminaristischen Unterrichte (SU), aller Übungen (Ü) und aller Tests (T):
Alle SUs und Üs finden jeweils am Donnerstag (in den ersten drei Blöcken) statt
SW KW
Datum
08.00-09.30
D212
10.00-11.30
DE36/1
12.15-13.45
D117/H3
1
14
02.04.15
2
15
09.04.15
SU-01
Ü1a-01
SU-02
3
16
16.04.15
Ü1c-01
Ü1b-01
SU-03
4
17
23.04.15
SU-04, T01
Ü1a-02
SU-05
5
18
30.05.15
Ü1c-02
Ü1b-02
SU-06
6
19
07.05.15
SU-07, T02
Ü1a-03
SU-08
7
20
14.05.15
8
21
21.05.15
SU-09, T03
Ü1b-03
SU-10
9
22
28.05.15
Ü1c-03
Ü1a-04
SU-11
10
23
04.06.15
SU-12, T04
Ü1b-04
SU-13
11
24
11.06.15
Ü1c-04
Ü1a-05
SU-14
12
25
18.06.15
SU-15, T05
Ü1b-05
SU-16
13
26
25.06.15
Ü1c-05
Ü1a-06
SU-17
14
27
02.07.15
SU-18, T06
Ü1b-06
SU-19
15
28
09.07.15
Ü1c-06
Ü1a-07
SU-20
16
29
16.07.15
SU-21, T07
Ü1b-07
SU-22
17
30
23.07.15
Ü1a+1b+1c-08
SU-23
Klausur
18
31
30.07.15
SU-25
Rückgabe
Himmelfahrt
SU-24
Abkürzungen:
ALG: Algorithmen
SW: Semesterwoche
KW: Kalenderwoche
SU-01, SU-02, ...
Seminaristischer Unterricht, Termin 01, 02, ...
Ü1a-01, Ü1a-02, ...
Ü1b-01, Ü1b-02, ...
Ü1c-01, Ü1c-02, ...
Übungsgruppe 1a, Termin 01, 02, ...
Übungsgruppe 1b, Termin 01, 02, ...
Übungsgruppe 1c, Termin 01, 02, ...
T01, T02, ...
Test 01, 02, ...
Hauptklausur: am Do 23.07.2015, 12.15 Uhr Raum D554
Rückgabe:
am Do 30.07.2015, 12.15 Uhr Raum D117/H5
Nachklausur:
Rückgabe
am Mo 28.09.2015, 10.00 Uhr Raum D554
am Do 01.10.2015, 10.00 Uhr? Raum ?
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 3
Wie bekommt man eine Note für den Übungsteil dieser LV?
In den ungeraden Kalenderwochen werden wir insgesamt 7 kleine Tests (T01 bis T07) schreiben, Bearbeitungszeit jeweils etwa 10 bis 15 Minuten. Die Aufgaben und Fragen in diesen Tests werden sich auf
den Stoff beziehen, der (im SU und in den Ü) vorher behandelt wurde. In jedem Test kann man maximal
20 Punkte erreichen. Mit 10 oder mehr Punkten hat man den Test bestanden, mit weniger Punkten hat
man den Test nicht bestanden. Wenn Sie 5 oder mehr der 7 Tests bestehen, bekommen Sie für den
Übungsteil die (undifferenzierte) Note m.E. (mit Erfolg), sonst die Note o.E. (ohne Erfolg).
Empfehlung: Schreiben Sie alle Tests mit, bei denen Ihnen das irgendwie möglich ist. Sparen Sie sich
die Möglichkeit, zwei Tests nicht zu bestehen (z.B. weil Sie einen schlechten Tag hatten oder nicht daran
teilnehmen konnten) bis zum Ende des Semesters auf. Wenn Sie an einem Test nicht teilnehmen, spielt
es keine Rolle, warum Sie nicht teilgenommen haben (S-Bahn hatte Verspätung, war krank, musste einen
hohen Lotto-Gewinn persönlich abholen etc.).
Außerdem wird aus Ihren 5 besten Testergebnissen (das ist eine Punktezahl zwischen 0 und 100) nach
der folgenden Tabelle eine differenzierte Übungsnote zwischen 1,0 und 5,0 berechnet:
Punkte (ab):
95
90
85
80
75
70
65
60
55
50
0-49
Note:
1,0
1,3
1,7
2,0
2,3
2,7
3,0
3,3
3,7
4,0
5,0
Diese differenzierte Übungsnote kann ihre Modulnote verbessern oder verschlechtern.
Wie bekommt man eine Modulnote für diese LV?
Um eine (differenzierte) Modulnote zu bekommen, muss man an einer Klausur teilnehmen (an der
Hauptklausur am Ende des SS15 oder an der Nachklausur kurz vor dem WS15/16). An den Klausuren
dürfen alle teilnehmen, die die Lehrveranstaltung MB2-ALG, Zug 1, belegt haben. In den Klausuren sind
jeweils 100 Punkte erreichbar. Nach der Tabelle im vorigen Abschnitt wird daraus die Klausurnote ermittelt.
Die Modulnote wird aus der der Klausurnote (Gewicht: 75%) und aus der differenzierten Übungsnote
(Gewicht: 25%) berechnet. Die folgenden Beispiele sollen zeigen, wie dabei gerundet wird:
Übungsnote Klausurnote
Rohergebnis
(gerundete) Note
2,3
2,7
(2,3 + 3 * 2,7) / 4 = 2,60
2,7
3,7
1,3
(3,7 + 3 * 1,3) / 4 = 1,90
2,0
2,0
4,0
(2,0 + 3 * 4,0) / 4 = 3,50
3,3
Unterlagen für Tests und Klausuren
Zu jedem der Tests dürfen Sie als Unterlage mitbringen:
1 Blatt, max. DIN A 4, beliebig beschriftet (von Hand oder mit Drucker/Kopierer, nur auf der Rückseite
oder nur auf der Vorderseite oder beidseitig, schwarz-weiß oder farbig, ordentlich oder chaotisch, ...).
Zur Klausur (und zur Nachklausur) dürfen Sie als Unterlagen mitbringen:
5 Blätter, max. DIN A 4, beliebig beschriftet (siehe oben).
Hinweis: 10 einseitig beschriebene Blätter sind zehn Blätter und nicht 5 Blätter!
Übungsgruppen
Wer zu welcher Übungsgruppe (1a, 1b bzw. 1c) gehört, wird nicht durch das Online Belegsystem festgelegt, sondern am Do 09.04.2015 kurz nach 08.00 Uhr im Raum D212). Wenn es für eine Übungsgruppe
mehr InteressentInnen gibt als Plätze, entscheidet das Los. Nur persönlich Anwesende können an den
Verlosungen teilnehmen.
S. 4, SS15
SU 1. Do 09.04.15, Block 1
Beuth-Hochschule
SU 1. Do 09.04.15, Block 1
1. Begrüßung
2. Namensschilder verteilen, schreiben, aufstellen.
Namensschilder bitte immer mitbringen und möglichst selbständig aufstellen.
Bitte schicken Sie mir per E-Mail ein Porträt-Foto (Passbild) von sich, damit ich Ihre Namen (leichter)
lernen kann. Ich verspreche, diese Bilder nur zu diesem Zweck zu benutzen und nicht weiterzugeben.
Mehrere Namen und Fotos in einer E-Mail sind natürlich auch ok.
3. Wie bekommt man zwei Noten für das Fach Algorithmen?
Ü-Note: 7 Tests, wenn man mindestens 5 besteht: m.E., sonst o.E.
Pro Test sind 20 Punkte erreichbar, ab 10 Punkten hat man bestanden.
Außerdem wird aus Ihren fünf besten Testergebnissen eine differenzierte Ü-Note (1.0 - 5.0) errechnet
Modul-Note: Klausur-Note (75%) und differenzierte Ü-Note (25%)
4. Übungen: Verteilung aller Anwesenden auf die 3 Übungsgruppen (1a, 1b, 1c)
Falls nötig werden Plätze verlost.
5. Lehrkraftnews abonnieren!
6. Arbeitsgruppen: Bestehen aus 2 Personen, die gemeinsam Projekte bearbeiten (siehe die Datei
Projekte.pdf auf meiner Netzseite). Jede Arbeitsgruppe braucht nur eine Lösung zu erstellen und
vorzuzeigen. Jede Arbeitsgruppe sollte zu jedem SU mindestens 1 Laptop mitbringen.
Frage: Wie viele Laptops sind jetzt anwesend?
Hat jemand noch Fragen zur Organisation dieser Lehrveranstaltung?
Einleitende Anmerkungen zu dieser LV
Die drei Punkte aus der Einleitung auf S. 1:
1. Rechnen Sie erst mal mit hohen Anforderungen (wenn Ihnen dann alles ganz leicht fällt, können Sie
Ihre Erwartungen immer noch "nach unten" anpassen).
2. Kommen Sie zu allen SUs und zu allen Üs !
3. Bei Problemen: Lassen Sie uns reden und versuchen, die Probleme zu verkleinern.
Außerdem:
4. Eignen Sie sich den Stoff aktiv an (und warten Sie nicht darauf, "von außen betankt zu werden").
5. Kommen Sie vorbereitet in die Übungen. Lesen Sie die Datei Projekte.pdf und andere Papiere
zu Hause durch (ungefähr ein Projekt alle 2 Wochen) und erstellen Sie dabei eine Liste mit Ihren Fragen.
In der Übung sollte es dann vor allem um die Beantwortung ihrer Fragen gehen (nicht um das Lesen der
Aufgaben).
6. Leihen Sie sich das Buch Java ist eine Sprache (von Ulrich Grude) in der Bibliothek.
7. Ich freue mich, wenn Sie Fragen haben und werde mich bemühen, sie zu beantworten. Bitte missbrauchen Sie mich aber nicht mit trivialen Fragen ("Wie spät ist es?", "Wann schreiben wir den nächsten
Test?", "Wann schreiben wir die Klausur?", "Wie viele Punkte braucht man in einem Test zum
Bestehen?" etc.). Stellen Sie solche Fragen erst an zwei oder drei TeilnehmerInnen dieser LV und schauen Sie im Internet nach. Wenn Sie intensiv nachgeforscht haben und keinen Erfolg hatten, dann dürfen
Sie gern zu mir kommen, aber möglichst nicht vorher.
8. Benutzen Sie zum Schreiben von Programmen und zum Notieren von Lösungen normalerweise einen
Bleistift und einen Radiergummi (keine Steinplatten und Meißel oder Ähnliches). Sie dürfen in allen
Tests und in den Klausuren mit Bleistift und Radiergummi schreiben.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 5
9. Wenn Sie zu Hause merken, dass Sie etwas nicht verstanden haben, dann sollten Sie erst mal ein oder
zwei andere TeilnehmerInnen dieser LV danach fragen. Wenn das nicht hilft, dürfen Sie mir (zu zweit
bzw. zu dritt) Ihr Problem per E-Mail beschreiben, und ich werde dann versuchen, Ihnen zu helfen.
Wer hat schon vor dem Studium an der Beuth ein paar Java-Programme geschrieben? (Sehr wenige)
Wer hat schon Programme in einer anderen Sprache als Java geschrieben? (Sehr wenige)
Jetzt geht es los mit dem Stoff!
Ziele dieser Lehrveranstaltung
Die Begriffe Programm und Algorithmus sollen behandelt werden.
Was haben diese Begriffe miteinander zu tun? Was unterscheidet sie voneinander?
Was versteht man unter der Zeitkomplexität eines Algorithmus?
Die Tilde-Notation und die Groß-O-Notation.
Einige wichtige Datenstrukturen (Reihungen, Listen, Bäume, Hashtabellen)
und Algorithmen zu ihrer Verwaltung und Bearbeitung sollen genauer behandelt werden.
Eine paar weitere Algorithmen sollen behandelt werden.
Was hat es mit den Algorithmen-Gruppen P und NP auf sich?
Welche Algorithmen gehören zur Gruppe P? Und welche zu NP?
Welche Algorithmen sind NP-vollständig? Sind die beiden Gruppen wirklich verschieden?
Internet-Zugang während der SUs
Kann jeder auf einen Bildschirm mit Internet-Verbindung sehen? Bitte öffnen Sie (auf meiner Netzseite)
die Datei AnfangsQuiz.txt. Wir behandeln hier ein paar Fragen am Anfang dieser Datei. Die übrigen Fragen sollen Sie zu Hause beantworten (mit einem Editor).
1. Woraus besteht ein Java-Programm? Nennen Sie nicht die kleinsten
Bestandteile (wie Zeichen oder Zeilen oder Methoden etc.), sondern die
größten sinnvollen Bestandteile eines Java-Programms.
-------------------------------------------------------------------------2. In Java unterscheidet man 2 Arten von Typen:
Primitive Typen und Referenztypen.
Wie viele primitive Typen gibt es und wie heißen sie?
-------------------------------------------------------------------------3. Zu jedem primitiven Typ gibt es eine Hüllklasse (engl. wrapper class).
Wie heißen diese Hüllklassen?
-------------------------------------------------------------------------4. Wie viele Referenztypen gibt es in Java?
Hier genügt eine sehr ungefähre Antwort.
-------------------------------------------------------------------------5. Vereinbaren Sie eine Variable namens summe vom Typ int mit dem
Anfangswert 123.
--------------------------------------------------------------------------
S. 6, SS15
SU 1. Do 09.04.15, Block 1
Beuth-Hochschule
Rekursion
Wie kann der Programmierer bewirken, dass eine Anweisung mehrmals ausgeführt wird?
(Indem er die Anweisung in den Rumpf einer Schleife schreibt).
Schon lange vor Schleifen hatten Mathematiker bereits eine andere "Wiederhol-Technik" erfunden.
Rekursive Definitionen:
Def. Binärzahl: Eine Binärzahl ist
entweder eine Binärziffer
oder eine Binärziffer gefolgt von einer Binärzahl
Def. Zeichenfolge: Eine Zeichenfolge ist
entweder eine leere-Folge
oder ein Zeichen gefolgt von einer Zeichenfolge
Def.: Fakultätsfunktion faku:
faku(0) = 1
faku(n) = n * faku(n-1)
// für alle n>0
Def.: Fibonacci-Funktion fibo:
fibo(0) = 0
fibo(1) = 1
fibo(n) = fibo(n-1) + fibo(n-2) // für alle n>1
Aufgabe-A: Wie kann man die Funktion faku als Java-Funktion programmieren?
Programmieren Sie sie jetzt in Ihren 2-Personen-Arbeitsgruppen.
1 static long faku(int n) {
2
// Liefert die Fakultaet von n.
3
// Verlaesst sich darauf, dass n nicht negativ ist.
4
if (n==0) return 1;
5
return n * faku(n-1);
6 }
Aufgabe-B: Wie kann man die Funktion fibo als Java-Funktion programmieren?
7 static long fibo(int n) {
8
// Liefert die n-te Fibonacci-Zahl
9
// Verlaesst sich darauf, dass n nicht negativ ist.
10
if (n==0) return 0;
11
if (n==1) return 1;
12
return fibo(n-1) + fibo(n-2);
13 }
Zur Entspannung: Was kostet ein Studium an der Beuth Hochschule?
Haushalt der Beuth Hochschule ca. 80 Millionen [Euro pro Jahr].
An der Beuth Hochschule studieren ca. 10 Tausend StudentInnen.
Also kostet das Studieren an der Beuth Hochschule ca. 8000 [Euro pro StudentIn und Jahr].
Ein Bachelor-Studium (6 Semester, 3 Jahre) kostet also ca. 24 Tausend [Euros pro StudentIn].
Pro Jahr hat eine StudentIn ca. 1000 Stunden Lehrveranstaltungen (LV)
(ca. 32 Wochen lang ca. 30 Stunden pro Woche).
Also kostet ein Stunde LV pro StudentIn ca. 8 Euro (1 Block: 16 Euro).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 7
Grundlagen zum Thema Rekursive Unterprogramme
Def.: Ein Unterprogramm (eine Methode, eine Funktion, eine Prozedur) ist rekursiv,
wenn sie sich (direkt oder indirekt) selbst aufruft.
Die Funktionen faku ist direkt rekursiv (im Rumpf von faku steht ein Aufruf von faku).
Wenn ein Unterprogramm u1 eine Unterprogramm u2 aufruft, und u2 ein Unterprogramm u3 aufruft,
und u3 ein Unterprogramm u4 aufruft, ... , und u17 wieder das Unterprogramm u1 aufruft,
dann ist u1 indirekt rekursiv (und das Gleiche gilt für u2 bis u17).
S. 8, SS15
SU 1. Do 09.04.15, Block 1
Beuth-Hochschule
Übung Ü-01 (Gruppe 1a am 09.04.2015, Gruppen 1c und 1b am 16.04.2015)
1. Jeder sollte sich auf einem Labor-Rechner einloggen (auch wenn er/sie später hauptsächlich auf einem
eigenen Laptop arbeiten will).
2. Erzeugen Sie unter Eclipse ein Java-Projekt namens LongSpeicher.
3. Erzeugen Sie im Projekt LongSpeicher eine Schnittstelle (Interface) namens LongSpeicher.
Den vollständigen Text dieser Schnittstelle finden Sie in der Datei Projekte.txt.
4. Erzeugen Sie im Projekt LongSpeicher eine Klasse (Class) namens LongSpeicher10.
Den unvollständigen Text dieser Klasse finden Sie ebenfalls in der Datei Projekte.txt.
5. Lesen Sie im Papier TippsFuerEclipse.pdf den Punkt
20. JUnit 3 unter Eclipse
durch und befolgen Sie ihn für das Projekt LongSpeicher.
6. Erzeugen Sie im Projekt LongSpeicher einen JUnit Test Case namens
LongSpeicher_Jut. Achten Sie darauf, ganz oben im New JUnit Test Case - Fenster den
RadioButton New JUnit 3 Test (und nicht: New JUnit 4 Test) zu wählen.
Den (fast) vollständigen Text dieser Datei finden Sie ebenfalls in der Datei Projekte.txt.
Ändern Sie die Zeile direkt unter der Kommentarzeile
// Der volle Name der zu testenden Klasse ("mit allen Paketen"):
so, dass dort der volle Name der zu testenden Klasse LongSpeicher10 steht. Falls Sie nicht sicher
sind, was "der volle Name einer Klasse ist", dann fragen Sie Ihre Kollegen danach bis Sie es sicher wissen.
7. Führen Sie den LongSpeicher_Jut als normales Java-Programm aus
(RunAs, Java Application).
Dadurch wird das Programm LongSpeicher10 getestet, und da es noch unvollständig (aber schon
kompilierbar und ausführbar) ist, werden viele Fehler angezeigt.
8. Führen Sie den LongSpeicher_Jut als JUnit Test aus
(RunAs, JUnit Test).
Dadurch wird das Programm LongSpeicher10 getestet, und da es noch unvollständig (aber schon
kompilierbar und ausführbar) ist, werden viele Fehler angezeigt. Die Ausgabe erfolgt aber in einer etwas
anderen Form als beim vorigen Punkt.
9. Lesen Sie die (noch unvollständige) Datei LongSpeicher10.java sorgfältig durch. Diskutieren
Sie mit Ihrer Gruppen-PartnerIn den Sinn der beiden Variablen:
private long[] speicher;
private int
nfi = 0; // naechster freier Index
Wozu ist die Variable nfi gut? Wann wird sie verändert? Wann wird sie benötigt?
Vervollständigen Sie sie dann diese Datei, indem Sie alle mit
// MUSS ERSETZT WERDEN
gekennzeichneten Zeilen durch "richtige Befehle" ersetzen.
10. Lesen Sie zwischendurch auch im Papier Projekte.pdf den Abschnitt
Projekt 1:Sammeln in einer unsortierten Reihung
durch.
Und achten Sie darauf, dass Sie nicht zu spät zum Mittagessen kommen (zumindest aber pünktlich kurz
vor 12.15 Uhr im Raum D117/H3 erscheinen können :-).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 9
SU 2. Do 09.04.15, Block 3
Allgemeine Form aller rekursiven Unterprogramme
1. Der Rumpf eines rekursiven Unterprogramms muss aus einer Fallunterscheidung bestehen
(meistens ist das eine if-Anweisung, es kann auch eine switch-Anweisung oder ein ähnliches Konstrukt sein).
2. Diese Fallunterscheidung muss unterscheiden zwischen
einfachen Fällen (in denen sich das Unterprogramm nicht wieder aufruft) und
rekursiven Fällen (in denen sich das Unterprogramm wieder aufruft).
3. Es muss mindestens einen einfachen Fall und mindestens einen rekursiven Fall geben.
Frage-01: Was wäre mit einem Unterprogramm, welches keinen einfachen Fall enthält?
(Es würde zu einer Endlosrekursion führen).
Frage-02: Was wäre mit einem Unterprogramm, welches keinen rekursiven Fall enthält?
(Es wäre nicht rekursiv).
Kurze Wiederholung: Parameter und Argumente von Methoden
Wenn man eine Methode vereinbart, darf man sie mit (0 oder mehr) Parametern versehen, z.B. so:
17
18
19
static String met(int n, String s) { // Zwei Parameter: n und s
... // Rumpf der Methode met
}
Wenn man eine Methode aufruft, muss man für jeden Parameter der Methode ein dazu passendes
Argument (einen Ausdruck des richtigen Typs) angeben, z.B. so:
33
34
35
36
int
int
...
...
n = ... ;
m = ... ;
met(17, "Hallo!) ...
met(2*n, "Nr."+m) ...
Kurz: Parameter sind Variablen, Argumente sind Ausdrücke.
Grundregel zum Schreiben einer rekursiven Methode:
Angenommen, Sie wollen eine rekursive Methode namens
static void rm (int n ) { ... }
schreiben.
1. Machen Sie sich vertraut damit, was die Methode rm machen soll, und üben Sie,
das präzise zu beschreiben (indem Sie es z.B. einer Kollegin erklären).
2. Empfehlung: Behandeln Sie im Rumpf von rm zuerst die einfachen Fälle.
3. Wenn Sie dann die rekursiven Fälle behandeln, sollten Sie beachten:
Sie dürfen (im Rumpf von rm) Ihre Methode rm beliebig oft aufrufen, aber nie mit
dem Parameter n als Argument:
40
41
42
static int rm(int n) { // Parameter n
... // Einfache Faelle werden behandelt
... rm(n) ... // n als Argument ist VERBOTEN
Als Argument (von rm) ist nur ein Ausdruck erlaubt,
dessen Wert näher bei einem einfachen Fall liegt als der Wert von n.
S. 10, SS15
SU 2. Do 09.04.15, Block 3
Beuth-Hochschule
Sorry, die folgenden Beispiele waren in der Vorlesung noch stellenweise falsch. Ich hoffe, dass sie jetzt
richtig sind.
Beispiel-01: Wenn Sie alle Werte von n, die kleiner oder gleich 0 sind,
als einfache Fälle behandelt haben, z.B. so:
if (n <= 0) System.out.println("Einfacher Fall!");
dann sind unter anderem folgende rekursive Aufrufe erlaubt:
rm(n-1), rm(n-2), rm(n-3), ...
rm(n/2), rm(n/3), rm(n/4), ...
Beispiel-02: Wenn Sie alle Werte von n, die kleiner als -1000 oder oder größer als +1000 sind,
als einfache Fälle behandelt haben, z.B. so:
if (n < -1000 || +1000 < n) System.out.println("Einfacher Fall!");
dann sind unter anderem folgende rekursive Aufrufe erlaubt:
rm(n-1),
rm(n/2),
rm(n+1),
rm(n*2),
rm(n-2),
rm(n/3),
rm(n+2),
rm(n*3),
rm(n-3),
rm(n/4),
rm(n+3),
rm(n*4),
...
...
...
...
Beispiel-03: Wenn Sie nur den Wert 0 von n als einfachen Fall behandelt haben, z.B. so:
if (n==0) System.out.println("Einfacher Fall!);
dann sind u.a. folgende rekursive Aufrufe erlaubt:
rm(n/2), rm(n/3), rm(n/4), ...
Aufrufe wie rm(n-1) oder rm(n+1) sind nicht erlaubt. Warum nicht?
(Wenn n z.B. gleich -3 ist, dann ist n-1 nicht näher beim einfachen Fall 0 als n.
Wenn n z.B. gleich +3 ist, dann ist n+1 nicht näher beim einfachen Fall 0 als n.)
Mehrere Parameter: Wenn rm mehrere Parameter p1, p2, p3, ... hat, dann
muss die gerade behandelte Einschränkung für mindestens einen davon gelten.
Aufgabe-01: Schreiben Sie eine rekursive Methode ("Schleifen dürfen hier nicht rein")
entsprechend der folgenden Spezifikation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void printBisDurch5Teilbar(int n) {
// Gibt die Zahlen n, n+1, n+2, ... aus, bis eine durch 5 teilbare
// Zahl ausgegeben wurde.
//
// Beispiele:
// Befehl:
Ausgegeben wird:
// printBisDurch5Teilbar(10);
10
// printBisDurch5Teilbar(11);
11 12 13 14 15
// printBisDurch5Teilbar(12);
12 13 14 15
// printBisDurch5Teilbar(13);
13 14 15
// printBisDurch5Teilbar(14);
14 15
// printBisDurch5Teilbar(15);
15
// printBisDurch5Teilbar(17);
17 18 19 20
if (n%5 == 0) {
printf("%d%n", n);
} else {
printf("%d ", n);
printBisDurch5Teilbar(n+1);
}
}
// Ein einfacher Fall
// Ein
// rekursiver Fall
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 11
Fibonacci-Zahlen, Fortsetzung:
Oben haben wir eine erste Definition der Funktion fibo gesehen (mit Rekursion, in 3 Zeilen).
Es gibt noch eine zweite Definition (ohne Rekursion, in 1 Zeile):
( )
1 1+√ 5
fibo(n) =
⋅
2
√5
n
( )
1 1−√ 5
−
⋅
2
√5
n
Erstaunlich: Obwohl die Wurzel aus 5 eine "sehr krumme Zahl mit unendlich vielen (nicht-periodischen) Nachpunktstellen ist", liefert diese Formel für jeden Wert von n die richtige ganze Zahl (natürlich
nur, wenn man "sehr genau" oder zumindest "genau genug" rechnet).
Anmerkung: Man kann diese zweite Definition in eine Java-Funktion übersetzten und einen "schmutzigen Trick" anwenden: Mit double-Werten rechnen und das Endergebnis in einen long-Wert umwandeln. Ab fibo(72) sind die Ergebnisse dann falsch, weil double nur eine begrenzte Genauigkeit hat.
Bei der rekursiven Lösung (die mit long-Werten rechnet) sind die Ergebnisse bis fibo(92) richtig
(also für größere Argumente als die Lösung mit double-Werten), aber ab fibo(93) sind die richtigen Ergebnisse größer als Long.MAX_VALUE (ca. 9 Trillionen) und es treten Überläufe auf.
Welche Definition der Funktion fibo finden Sie leichter verstehbar,
die mit Rekursion oder die ohne Rekursion?
Zahlensysteme (Stellenwertsysteme)
Die Begriffe Stellenwertsystem, Zahl, Ziffer, Stelle, Stellenwert, Ziffernwert und Beitrag werden im Papier Zahlensysteme.pdf (5 Seiten) erläutert. Diese Begriffe braucht man, um einige der Aufgabe im Papier RekursionAufgaben.pdf zu lösen. Außerdem gehört es zur Allgemeinbildung eines Informatikers, alle Stellenwertsysteme zu beherrschen (was gar nicht so schwer ist, weil alle Stellenwertsysteme
nach dem selben Prinzip funktionieren).
In 2 Wochen (am 23.04.2015) schreiben wir den Test 1. Dazu sollten Sie alle Fragen im
AnfangsQuiz.txt beantworten können, mit dem Papier Zahlensysteme.pdf gut vertraut sein
und Rekursion möglichst schon ganz einfach finden.
S. 12, SS15
SU 3. Do 16.04.15, Block 3
Beuth-Hochschule
SU 3. Do 16.04.15, Block 3
Kurze Wiederholung
1. Woraus muss der Rumpf jeder rekursiven Methode bestehen? (Aus einer Fallunterscheidung).
2. Was für Fälle müssen unterschieden werden? (Einfache Fälle und rekursive Fälle).
3. Angenommen, Sie schreiben eine rekursive Methode namens rm17 mit einem Parameter namens
karlHeinz. Was für ein rekursiver Aufruf ist dann grundsätzlich verboten? ( rm17(karlHeinz) ).
4. Was muss für das Argument A in einem rekursiven Aufruf rm17(A) gelten? (Der Wert des Arguments
A muss näher an einem einfachen Fall liegen als der Wert des Parameters karlHeinz).
Rekursion (Fortsetzung)
Tipp: Es ist keine gute Idee, einen Kran mit ins Fitnessstudio zu nehmen, und den die Gewichte heben
zu lassen. Die Lösungen der folgenden Aufgaben irgendwo zu suchen und abzuschreiben, ist auch nicht
wirklich nützlich. Nur "selbst anheben" ist ein sinnvolles Training.
Schreiben Sie Java-Methoden entsprechend den folgenden Spezifikationen (alle Methoden dürfen sich
darauf verlassen, dass sie nicht mit negativen Argumenten aufgerufen werden):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static long fibo(int n) {
// Liefert die n-te-Fibonacci-Zahl, entsprechend der Definition
// fibo(0) gleich 0,
// fibo(1) gleich 1,
// fibo(n) gleich fibo(n-1) + fibo(n-2) fuer n>1
if (n==0) return 0;
if (n==1) return 1;
return fibo(n-1) + fibo(n-2);
}
static long anzMoeg(int s) {
// Wie viele Moeglichkeiten haben Sie, eine Treppe mit s Stufen
// hinaufzugehen, wenn Sie bei jedem Schritt entweder eine oder
// zwei Stufen nehmen koennen? Diese Methode liefert die Antworten.
if (s==1) return 1; // 1
if (s==2) return 2; // 1 1 , 2
return anzMoeg(s-1) + anzMoeg(s-2);
}
Was für Zahlen sind int-Werte? 10-er-Zahlen? 16-er-Zahlen? 2-er-Zahlen?
Empfehlung: Stellen Sie sich int-Werte als abstrakte Zahlen vor, die in keinem bestimmten Zahlensystem dargestellt sind, sich aber natürlich in jedem Zahlensystem darstellen lassen.
Wenn ein Java-Ausführer mit int-Werten rechnet und dabei 7 durch 2 teilt, was kommt dann raus?
(3, und nicht etwa 3.5). Durch welche Rechenoperation kann man aus einem int-Wert n "die niedrigstwertige 10-er-Ziffer" entfernen? Beispiele: Aus 123 soll 12 und aus 37 soll 3 werden etc.
(Rechenoperation: n/10.) Anmerkung: Das klappt sogar, wenn n einen negativen Wert enthält!
19 static int anz10ErZiff(int n) {
20
// Wie viele Ziffern braucht man, um n als 10-er-Zahl darzustellen?
21
// Diese Methode liefert die Antworten.
Wiederholung einiger Begriffe aus Programmieren 1
Was ist das wichtigste Grundkonzept der meisten Programmiersprachen?
(Das Konzept einer Variablen, deren Wert man beliebig oft verändern kann, z.B. durch Zuweisungen).
Alle Befehle in allen Programmiersprachen kann man in 3 Gruppen einteilen. Welche 3 Gruppen?
Vereinbarung (declaration) "Erzeuge ..."
Ausdruck
(expression) "Berechne den Wert des Ausdrucks ..."
Anweisung (statement) "Tue die Werte ... in die Wertebehälter ..."
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 13
Übung Ü-02 (Gruppe 1a am 23.04.2015, Gruppen 1c und 1b am 30.04.2015)
Bearbeiten Sie das Projekt 2 (in der Datei Projekte.pdf und Projekte.txt)
Erstellen Sie die Klasse LongSpeicher20 wie folgt:
1. Erzeugen Sie in Ihrem Eclipse-Projekt namens LongSpeicher eine
Klasse namens LongSpeicher20.
2. Kopieren Sie den Inhalt Ihrer Klasse LongSpeicher10 (die Sie in der vorigen Übung und zu Hause
programmiert und getestet haben) in die Klasse LongSpeicher20 und ersetzen Sie in der Kopie alle
Vorkommnisse von "LongSpeicher10" durch "LongSpeicher20".
3.Ersetzen Sie in der neuen Datei LongSpeicher20.java die Methode index durch die in der Datei Projekte.txt (für das Projekt 2) vorgegebene Methode index. Darin kommen mehrere Auslassungen
... vor. Ersetzen Sie diese Auslassungen durch geeignete Java-Ausdrücke.
Beachten Sie: Für das Ergebnis i eines Aufrufs index(n) soll gelten:
Wenn n im speicher vorkommt, dann soll i der Index von n sein
(d.h. dann soll speicher[i] == n gelten).
Wenn n noch nicht im speicher vorkommt, dann soll i der Index sein, an dem n in den speicher
eingefügt werden sollte
(d.h. speicher[i] sollte die kleinste Komponente von speicher sein, die größer als n ist).
4. Passen Sie dann die Methode fuegeEin den neuen Umständen an
(dass der speicher aufsteigend sortiert sein soll).
Empfehlung: Behandeln Sie zuerst den Fall, dass ein Einfügen nicht möglich ist
(weil der speicher bereits voll ist).
Beachten Sie: Doppelgänger (mehrere gleiche long-Werte im speicher) sollen in diesem Projekt
verboten sein. Dadurch wird das Programmieren ein bisschen einfacher.
Tipp: Möglicherweise müssen Sie "viele Komponenten der Reihung speicher"
um eine Position "nach rechts" verschieben, ehe Sie n in den speicher einfügen können.
5. Passen Sie dann die Methode loesche den neuen Umständen an.
Empfehlung: Behandeln Sie zuerst den Fall, dass ein Löschen von n nicht möglich ist
(weil n im speicher gar nicht vorkommt).
Tipp: Möglicherweise müssen Sie "viele Komponenten der Reihung speicher"
um eine Position "nach links" verschieben, um n zu löschen.
6. Passen Sie dann die Methode istDrin den neuen Umständen an.
Achtung: Dabei dürfen Sie keine if-Anweisung (und keine Schleife) verwenden
(weil es auch ohne geht und ohne if-Anweisung leichter lesbar ist).
7. Testen Sie Ihre Klasse LongSpeicher20,
zuerst, indem Sie zusätzliche Testbefehle in die main-Methode einfügen,
und dann mit dem Programm LongSpeicher_Jut. Dazu müssen Sie den vollen Namen der Klasse
LongSpeicher20 an der richtigen Stelle in die Datei LongSpeicher_Jut.java einfügen.
S. 14, SS15
SU 4. Do 23.04.15, Block 1
Beuth-Hochschule
SU 4. Do 23.04.15, Block 1
Test 1 (47 TeilnehmerInnen gaben einen Test ab).
Wiederholung einiger Begriffe aus Programmieren 1
Was ist das wichtigste Grundkonzept der meisten Programmiersprachen?
(Das Konzept einer Variablen, deren Wert man beliebig oft verändern kann, z.B. durch Zuweisungen).
Alle Befehle in allen Programmiersprachen kann man in 3 Gruppen einteilen. Welche 3 Gruppen?
Vereinbarung (declaration) "Erzeuge ..."
Ausdruck
(expression) "Berechne den Wert des Ausdrucks ..."
Anweisung (statement) "Tue die Werte ... in die Wertebehälter ..."
In praktisch allen Programmiersprachen gibt es Unterprogramme.
In vielen Sprachen unterscheidet man 2 Arten von Unterprogrammen. Welche 2 Arten?
Funktionen (liefern einen Wert,
Prozeduren (verändern Wertebehälter,
jeder Aufruf ist ein Ausdruck)
jeder Aufruf ist eine Anweisung)
Was ist eine Methode?
Ein Unterprogramm (eine Funktion oder Prozedur) die innerhalb einer Klasse vereinbart wurde.
Projekt 2
Was ist eine LongSpeicher-Klasse?
(Eine Klasse, die die Schnittstelle LongSpeicher implementiert).
Was ist ein LongSpeicher-Objekt (kurz: Was ist ein LongSpeicher)?
(Ein Objekt einer LongSpeicher-Klasse)
Wie heißen die drei Methoden in der Schnittstelle LongSpeicher?
(fuegeEin, loesche, istDrin)
Wie heißt die LongSpeicher-Klasse, die Sie im Projekt 1 geschrieben haben?
(LongSpeicher10)
Als was ist bei einem LongSpeicher10-Objekt der Speicher implementiert?
(Als eine unsortierte Reihung von long-Variablen)
Angenommen wir haben 2 LongSpeicher10-Objekte vereinbart:
LongSpeicher ls1 = new LongSpeicher10(100);
LongSpeicher ls2 = new LongSpeicher10(100_000);
Zeitmessungen haben ergeben, dass ein Aufruf von ls1.fuegeEin(...)
(auf einem etwas älteren Computer) ziemlich genau 1 Millisekunde dauert.
Ungefähr wie lange dauert dann ein Aufruf von ls2.fuegeEin(...) vermutlich?
(Ebenfalls etwa 1 Millisekunde)
Angenommen, die Speicher ls1 und ls2 sind beide ganz voll und n ist ein long-Wert, der weder in
ls1 noch in ls2 vorkommt. Was gilt dann vermutlich für den Zeitbedarf von ls1.istDrin(n) und
ls2.istDrin(n)? Werden diese beiden Aufrufe auch etwa gleich viel Zeit benötigen?
(Nein, der Aufruf ls2.istDrin(n) wird vermutlich etwa 1000 mal so viel Zeit benötigen wie der
Aufruf ls1.istDrin(n))
Für Aufrufe der Methode loesche gilt ganz Ähnliches wie für istDrin: Je größer die Sammlung,
desto länger dauert es, einen bestimmten long-Wert zu finden und zu löschen.
Kurze Bewertung von LongSpeicher10 (Implementierung des Speichers als unsortierte Reihung):
fuegeEin ist unabhängig von der Größe des Speichers und sehr schnell,
loesche und istDrin sind abhängig von der Größe des Speichers und eher langsam.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 15
Was ist der Unterschied zwischen Projekt 1 (d.h. LongSpeicher10)
und Projekt 2 (LongSpeicher20)?
(Im Projekt 2 sollen Sie den Speicher als sortierte Reihung implementieren).
SU 5. Do 23.04.15, Block 3
Was ist so toll an Logarithmen?
Bevor es Taschenrechner gab: Mit Hilfe von Logarithmentafeln kann man (aufwendige) Multiplikationen durch (deutlich weniger aufwendige) Additionen ersetzen. Das war unter anderem bei der Navigation
von Schiffen auf hoher See wichtig.
Wie viele Ziffern braucht man, um eine (positive) Zahl z als 10-er-Zahl darzustellen?
(etwa log10(z) viele Ziffern).
Wie viele Ziffern braucht man, um eine (positive) Zahl z als b-er-Zahl darzustellen?
(etwa logb(z) viele Ziffern).
Wie oft kann/muss man eine Reihung (engl.: an array) der Länge n in zwei (ungefähr) gleich lange
Hälften teilen, und diese Hälften in Viertel teilen etc., bis man lauter Reihungen der Länge 1 hat?
(etwa log2(n) mal).
Im Fach Algorithmen ist der Logarithmus zur Basis 2 besonders wichtig.
Mit log(n) ist ab jetzt immer log2(n) ("der Logarithmus zur Basis 2") gemeint.
Was ist so toll an sortierten Reihungen?
In einer sortierten Reihung kann man sehr schnell suchen (z.B. mit der Methode istDrin). Der entsprechende Such-Algorithmus wird binäres Suchen genannt.
Beispiel: Angenommen, wir haben eine sortierte Reihung von long-Werten namens r:
long[] r = {8, 13, 21, 35, 47, 59, 62, 74, 86, 97, 108, 114, 129, 134, 145};
Index i
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
r[i]
8
13
21
35
47
59
62
74
86
97
108
114
129
134
145
Schritt
4
3
4
2
4
3
4
1
4
3
4
2
4
3
4
Angenommen, wir suchen die Zahl n gleich 62.
Dann vergleichen wir n der Reihe nach mit
r[7] (n ist kleiner), r[3] (n ist größer), r[5] (n ist größer), r[6] (n ist gleich, gefunden)
Angenommen, wir suchen die Zahl n gleich 108.
Dann vergleichen wir n der Reihe nach mit
r[7] (n ist größer), r[11] (n ist kleiner), r[9] (n ist größer), r[10] (n ist gleich, gefunden)
Angenommen, wir suchen die Zahl n gleich 29.
Dann vergleichen wir n der Reihe nach mit
r[7] (n ist kleiner), r[3] (n ist kleiner), r[1] (n ist größer), r[2] (n ist ungleich, nicht gefunden)
Der folgende Baum soll deutlich machen, bei welchem Schritt wir n
mit welcher Komponenten r[i] vergleichen (angegeben ist nur der Index i):
Schritt 1:
Schritt 2:
Schritt 3:
Schritt 4:
7
+---------+----------+
3
11
+----+----+
+-----+-----+
1
5
9
13
+--+--+
+--+--+
+--+--+
+--+--+
0
2
4
6
8
10
12
14
S. 16, SS15
SU 5. Do 23.04.15, Block 3
Beuth-Hochschule
Im Projekt 2 (genau wie im im Projekt 1) wollen wir nicht "in der gesamten Reihung namens
speicher" suchen, sondern nur im "schon belegten Teil" speicher[0 .. nfi-1].
Die (ungefähre) Mitte einer Teilreihung berechnen: Angenommen, von und bis sind zwei Indizes für
die Reihung speicher (und von ist nicht größer als bis). Wie kann man den Index berechnen, der
möglichst genau zwischen von und bis liegt?
int mitteF = (von + bis) / 2;
// FALSCH Ueberlauf fuer sehr grosse von und bis
int mitteR = von + (bis-von) / 2; // RICHTIG
Beispiel: Wenn von gleich 1 Milliarde und bis gleich 1.5 Milliarden ist, dann ist
mitteF: -897.483.648
mitteR: 1.250.000.000
// Falsch
// Richtig
Programmieren Sie: Papier Projekte.pdf, S. 10, die Methode int index(long n)
Setzten Sie dabei voraus, dass die Teilreihung speicher[0 .. nfi-1] aufsteigend sortiert ist.
Zur Entspannung: Al-Khwarizmi (ca. 780-850)
Abu Ja'far Muhammad ibn Musa Al-Khwarizmi war ein islamischer Mathematiker, der in Bagdad lebte,
über Indisch-Arabische Zahlen schrieb und zu den ersten gehörte, die die Ziffer 0 benutzten. Aus seinem
Namen Khwarizmi entstand (durch Übertragung ins Latein und dann in andere Sprachen) das Wort Algorithmus. Eine seiner Abhandlungen heißt Hisab al-jabr w'al-muqabala (auf Deutsch etwa: "Über das
Hinüberbringen". Gemeint ist damit: Von einer Seite einer Gleichung auf die andere). Aus dem arabischen al-jabr entstand unser Wort Algebra.
Papier Projekte.pdf, S. 10, Aufgabe-01
Lösung:
Ergebnisse der Funktion index:
n
10
20
25
35
55
65
index(n)
0
0
1
2
4
5
Papier Projekte.pdf, S. 11, Aufgabe-03
Lösung:
Zweierpotenz
ungefähr entsprechende Zehnerpotenz
210
103
1 Tausend
1 thousend
220
106
1 Million
1 million
30
9
1 Milliarde
1 billion
12
2
40
10
deutsches
Zahlwort
amerikanisches
Zahlwort
2
10
1 Billion
1 trillion
250
1015
1 Billiarde
1 quadrillion
260
1018
1 Trillion
1 quintillion
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 17
Variablen als Bojen darstellen
Betrachten Sie im Papier JavaBuoys.pdf auf S. 2 das Example-01 (Vereinbarung von drei Variablen namens anna, bert und carl).
Eine Variable besteht aus mindestens 2 Teilen: Einer Referenz und einem Wert.
Primitive Variablen können zusätzlich noch einen Namen haben.
Referenz-Variablen können zusätzlich noch einen Namen und/oder einen Zielwert haben.
Der Name einer Variablen (falls vorhanden) wird vom Programmierer festgelegt.
Die anderen Teile (Referenz, Wert, Zielwert) werden vom Ausführer erzeugt und verwaltet.
Der Ausführer muss die Referenzen von Variablen so wählen, dass sie eindeutig sind (verschiedene Variablen müssen verschiedene Referenzen haben). Das gilt insbesondere dann, wenn verschiedene Variablen gleiche Namen haben.
Achtung: Im Internet wird an vielen Stellen nicht klar zwischen dem Wert einer Variablen und dem Zielwert einer (Referenz-) Variablen unterschieden.
Spezifisch Java 1: In Java ist der Ziel-Wert einer Referenz-Variablen immer ein Objekte (z.B. ein
String-Objekt oder ein Integer-Objekte oder ein Reihungs-Objekt etc.). In C/C++ kann eine Referenzvariable auch auf einen primitiven Wert referieren (z.B. auf einen int-Werte oder einen floatWerte etc.). Statt "referieren" kann man auch "zeigen" sagen (aber "referieren" klingt entschieden professioneller :-).
Spezifisch Java 2: In Java sind Werte immer relativ kleine Gebilde
(typischerweise nicht größer als 8 Bytes). Zielwerte können dagegen sehr groß sein (z.B. kann ein
String-Objekt oder eine BigInteger-Objekt oder eine Reihung mehrere Megabyte oder sogar Gigabyte Speicher belegen).
Einfache Regeln für Zuweisungen und für Vergleiche mit ==
Eine Zuweisung zwischen zwei Variablen: x = y;
kopiert immer den Wert von y in das Wertkästchen von x.
Ein Vergleich zwischen zwei Variablen: x==y
vergleicht immer die Werte von x und y (nicht die Zielwerte!).
Komplizierte Regel für equals-Methoden
In Java enthält jedes (!) Objekt eine Methode boolean equals(Object ob)
Was genau diese Methode macht legt der Programmierer der betreffenden Klasse fest.
Deshalb gibt es sehr viele verschiedene equals-Methoden.
Beispiele:
Die in der Klasse String vereinbarte equals-Methode vergleicht Ziel-Werte.
Die in der Klasse StringBuilder vereinbarte equals-Methode vergleicht Werte.
Eine wichtige Aufgabe zum Thema Rekursion:
Papier RekursionAufgaben.pdf, Aufgabe-31 (ab S. 8): Einen Farbeimer rekursiv programmieren
S. 18, SS15
SU 6. Do 30.04.15, Block 3
Beuth-Hochschule
SU 6. Do 30.04.15, Block 3
Was bedeutet oder bezeichnet der Name einer Referenzvariable?
Angenommen, wir haben folgende Referenzvariable:
StringBuilder stb = new StringBuilder("ABC");
Die vier Teile der Variablen stb als (ASCI-) Boje dargestellt:
|stb|
|
<100>
|
[<110>]
|
["ABC"]
Name
Referenz
Wert
Zielwert
In jedem der folgenden 5 Befehle kommt der Variablenname stb vor.
Welchen Teil der Variable bezeichnet dieser Name in den einzelnen Befehlen?
(Auch hier soll pln eine Abkürzung für System.out.println sein).
1 if (stb == ...) ...
2 stb.append("ZZ");
3 stb = ... ;
4 ... = stb;
5 pln(stb);
//
//
//
//
//
//
//
//
Der Name stb bezeichnet:
Den Wert [<110>]
Den Zielwert ["ABC"] (ein StringBuilder-Objekt)
Die Referenz <100>, die auf das Wertkästchen zeigt
(der "alte Wert" der Variabeln ist hier nicht wichtig).
Den Wert [<110>]
Den Wert, falls der gleich null ist, und sonst
die Zeichenfolge "ABC" im Zielwert.
Man muss also immer aus dem Zusammenhang erkennen, welcher Teil der Variablen
mit dem Namen der Variablen gemeint ist.
Projekt 2: Vor- und Nachteile sortierter Reihungen
Vorteil (im Vergleich zu unsortierten Reihungen): Das Suchen (die Methode istDrin) ist, vor allem
bei langen Reihungen, sehr schnell (z.B. bei 1 Milliarde Komponenten in einem schlimmsten Fall 30
Such-Schritte statt bei einer unsortierten Reihung im Durchschnitt 500 Millionen Such-Schritte).
Nachteil (im Vergleich zu unsortierten Reihungen): Das Einfügen (die Methode fuegeEin) braucht
bei langen Reihungen viel mehr Zeit als bei unsortierten Reihungen (bei einer Reihung der Länge n im
Durchschnitt n/2 Verschiebe-Schritte).
Was ist mit dem Löschen (mit der Methode loesche)?
(Dauert bei unsortierten und sortierten Reihungen ungefähr gleich lang:
Bei einer unsortierten Reihung der Länge n braucht man im Durchschnitt n/2 Such-Schritte, um die zu
löschende Komponente zu finden, das anschließende Löschen geht in einem Schritt.
Bei einer sortierten Reihung geht das Suchen der zu löschenden Komponente in sehr wenigen Schritten,
aber das anschließende Löschen kostet im Durchschnitt n/2 Verschiebe-Schritte)
Wichtige Eigenschaften von Reihungen (important characteristic traits of arrays)
1. Die Komponenten von Reihungen sind veränderbare Variablen
(nicht Werte oder unveränderbare Variablen).
2. Die Komponenten einer Reihung können zu einem primitiven Typ oder zu einem Referenztyp gehören
(Beispiele für Reihungstypen: int[], char[], ... und Integer[], String[], ...).
3. Jeder (lesende oder schreibende) Zugriff auf eine Komponente r[i] einer Reihung r dauert ungefähr
gleich lang (egal wie klein oder groß der Index i ist).
4. Ein Zugriff auf eine Reihungskomponente r[i] "geht sehr schnell" (die entsprechenden Maschinenbefehle gehören zu den schnellsten Befehlen heute üblicher Computer).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 19
5. Nachdem eine Reihung (vom Ausführer) erzeugt wurde, kann ihre Länge (die Anzahl ihrer Komponenten) nicht mehr geändert werden (kurze Merkform: "Reihungen sind aus Beton").
Diese letzte Eigenschaft ist sehr negativ. Sie kann zu "Speicherplatz-Verschwendung" führen, weil eine
Reihung auch "im maximalen Fall" lang genug sein muss, auch wenn dieser Fall nur sehr selten oder fast
nie eintritt.
Mit anderen Worten:
Nachteil: Eine Sammlung, die auf einer (unsortierten oder sortierten) Reihung beruht, belegt immer
"maximal viel Speicherplatz", auch dann, wenn man noch gar keine oder erst ganz wenige Komponenten
eingefügt hat.
Frage: Kann man eine Sammlung nicht so strukturieren, dass sie Platz für 10 Komponenten benötigt,
wenn man 10 Komponenten eingefügt hat, und erst dann Platz für 1 Million oder 1 Milliarde Komponenten benötigt, wenn man 1 Million oder 1 Milliarde Komponenten eingefügt hat?
Im Projekt 3 sollen Sie eine positive Antwort auf diese Frage implementieren.
Betrachten Sie in der Datei Projekte.pdf auf S. 12 die (noch unvollständige) Vereinbarung der Klasse
LongSpeicher30.
Fällt Ihnen irgend etwas Besonderes an dieser Klasse auf?
(Innerhalb der Klasse LongSpeicher30 wird eine Klasse Knoten vereinbart).
Wie viele Attribute (engl. fields) werden in jedes LongSpeicher30-Objekt eingebaut?
Und von welchem Typ sind diese Attribute? Und wie heißen sie?
(2 Attribute, siehe Zeilen 22 und 23. Sie sind vom Typ Knoten und heißen EDK und ADK).
Nein, ein Attribut namens Aldi, Lidle oder Netto gibt es hier nicht (die haben mir leider noch keine Werbevertrag angeboten :-).
Angenommen, wir vereinbaren eine Variable namens lob (wie "Listen-Objekt") wie folgt:
LongSpeicher30 lob = new LongSpeicher30();
Wie sieht diese Variable lob als Boje dargestellt aus?
Etwa so (die Referenzen <50>, <100>, <200> und die Referenz-Werte [<60>], [<110>],
[<210>] wurden wie immer vom Ausführer "nach seinem Geschmack" gewählt):
lob
50
60
ADK
EDK
100
200
110
210
next
210
next
null
data
0
data
0
Die Attribute (Variablen) next und data in den Knoten-Objekten ADK und EDK wurden hier vereinfacht dargestellt (nur durch ihren Namen und ihren Wert, ihre Referenz wurde weggelassen).
S. 20, SS15
SU 6. Do 30.04.15, Block 3
Beuth-Hochschule
Wenn noch Zeit ist: Programmieren Sie die Methode Knoten vorgaenger(long n)
(in der Klasse LongSpeicher30).
In diese Liste lob sollen jetzt 3 Komponenten eingefügt werden, durch die folgenden Befehle:
lob.fuegeEin(55);
lob.fuegeEin(33);
lob.fuegeEin(44);
Zur Entspannung: Wie lernt man? Ein simples Modell.
Angenommen, Sie sollen 1024 kleine Einzelteile ("Perlen der Länge 1 Millimeter") zu einer ungefähr
einen Meter langen Kette zusammenfügen. Dann können Sie folgendermaßen vorgehen:
1. Sie verbinden je zwei Einzelteile zu einem 2-er-Teil. Das sind 500 Arbeitsschritte. Sie sehen kaum
einen Fortschritt, weil ein 2-er-Teil nicht viel länger aussieht als ein Einzelteil.
2. Sie verbinden je zwei 2-er-Teile zu einem 4-er-Teil. Das sind 250 Arbeitsschritte. Immer noch ist
kaum ein Fortschritt zu sehen, denn die 4-er-Teile sind noch sehr kurz im Vergleich zum ein Meter langen Endergebnis.
3. Sie verbinden je zwei 4-er-Teile zu einem 8-er-Teil. 125 Arbeitsschritte.
...
9. Sie verbinden je zwei 256er-Teile zu einem 512er-Teil (2 Arbeitsschritte). Die Ergebnisse sind immer
noch viel kürzer als das Endergebnis.
10. Sie verbinden zwei 512er-Teile zu einem 1024er-Teil. Das ist nur ein einziger Arbeitsschritt, aber
der Fortschritt ist beeindruckend: Aus 50 Zentimeter langen Teilen wird ein 100 Zentimeter langes Ganzes.
Falls beim Lernen in unseren Gehirnen etwas (entfernt) Ähnliches abläuft, dann muss man sehr geduldig
sein: Erst ganz am Ende eines komplizierten Lernvorgangs sieht man einen "großen Fortschritt". Der
letzte Schritt eines Lernvorgangs ist manchmal ein so genanntes Aha-Erlebnis.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 21
SU 7. Do 07.05.15, 1. Block
Test 2
Verkettete Listen (Projekt 3)
Im vorigen SU haben wir uns den vorgegebenen Teil der Klasse LongSpeicher30
(in der Datei Projekte.pdf, S. 12) angesehen.
Was war besonders auffällig oder bemerkenswert an dieser Klasse?
(Sie enthält eine geschachtelte Klasse. Diese Klasse heißt Knoten)
Wie viele Attribute (Variablen) werden in jedes LongSpeicher30-Objekt eingebaut?
Wie heißen diese Attribute und zu welchem Typ gehören sie?
(2 Attribute namens EDK und ADK vom Typ Knoten).
Ein neues (noch leeres) LongsSpeicher30-Objekt enthält also schon 2 Knoten-Objekte namens EDK
und ADK. Diese Knoten bezeichnen wir als Dummy-Knoten ("Strohmann-Knoten", "Pseudo-Knoten"),
um sie von den "richtigen Knoten" zu unterscheiden, die später (von der Methode fuegeEin) erzeugt
werden. Ein LongSpeicher30-Objekt, in das schon 3 long-Werte eingefügt wurden, sieht etwa so
aus:
ADK
EDK
100
200
110
210
next
240
next
230
next
220
next
210
next
null
data
0
data
...
data
...
data
...
data
...
In der Klasse LongSpeicher30 soll die folgende Methode vereinbart werden, die wir jetzt gemeinsam entwickeln:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private Knoten vorgaenger(long n) {
// Liefert einen Knoten k fuer den gilt: k.next.data == n
// (d.h. k ist der Vorgaenger eines Knotens,
// dessen data-Komponente gleich n ist).
// Falls n in dieser Sammlung nicht vokommt, ist k gleich dem EDK.
// Die gesuchte Zahl n in den End-Dummy-Knoten eintragen
// (spaetestens dort wird sie dann gefunden)
EDK.data = n;
// Die Suche beginnt mit dem Anfangs-Dummy-Knoten:
Knoten hier = ADK;
while (hier.next.data != n) hier = hier.next;
return hier;
}
In Zeile 9 wenden wir einen kleinen Trick an (und damit wir ihn anwenden können gibt es den EndDummy-Knoten EDK): Wir tragen den gesuchten long-Wert n in die data-Komponente des EDK ein.
Dadurch sind wir sicher, mit der anschließenden Such-Schleife den Wert n wieder zu finden, entweder in
einem richtigen Knoten oder aber im EDK.
Schreiben Sie jetzt (am besten in Ihren 2-Personen-Arbeitsgruppen) die Methoden fuegeEin.,
istDrin und loesche (am besten in dieser Reihenfolge). Seien Sie möglichst faul und schreiben Sie
möglichst wenige Befehle in die einzelnen Methoden!
S. 22, SS15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
SU 7. Do 07.05.15, 1. Block
Beuth-Hochschule
// --------------------------------------------------------------------public boolean fuegeEin(long n) {
// Fuegt n in diesen Speicher ein und liefert true.
ADK.next = new Knoten(ADK.next, n);
return true;
}
// --------------------------------------------------------------------public boolean loesche(long n) {
// Loescht einen Knoten, der die Zahl n enthaelt, und liefert true.
// Liefert false falls n nicht in diesem Speicher vorkommt.
Knoten vor = vorgaenger(n);
// Wenn n in dieser Sammlung nicht vorkommt:
if (vor.next == EDK) return false;
// Wenn n in dieser Sammlung vorkommt:
vor.next = vor.next.next;
return true;
}
// --------------------------------------------------------------------public boolean istDrin(long n) {
// Liefert true genau dann wenn n in diesem Speicher vorkommt.
return vorgaenger(n).next != EDK;
}
// ---------------------------------------------------------------------
Zur Entspannung: Alan Mathison Turing (1912-1954), einer der Begründer der Informatik
Bevor man die ersten elektronischen Computer baute, konzipierte und untersuchte der Mathematiker
Turing eine Rechenmaschine, die so einfach war, dass niemand an ihrer prinzipiellen Realisierbarkeit
zweifelte. Eine solche Turing-Maschine besteht aus einem unbegrenzt langen Band, welches in kleine
Abschnitte eingeteilt ist, von denen jeder genau ein Zeichen eines endlichen Alphabets aufnehmen kann.
Ein Schreib-Lese-Kopf über dem Band kann bei jedem Arbeitsschritt der Maschine das Zeichen auf dem
aktuellen Abschnitt lesen und in Abhängigkeit davon ein bestimmtes Zeichen auf den aktuellen Abschnitt schreiben und einen Abschnitt nach links oder rechts weiter rücken. Ein Programm für eine solche Maschine besteht aus einer endlichen Menge von Befehlen der folgenden Form:
"Wenn das aktuelle Zeichen gleich X ist, dann schreibe Y und gehe einen Abschnitt nach links bzw.
nach rechts bzw. bleib wo du bist" (wobei X und Y beliebige Zeichen des Alphabets sind).
Wichtige Erkenntnis 1: Es gibt viele (präzise definierte, mathematische) Probleme, die man mit Hilfe einer solchen Turing-Maschine lösen kann (z. B. das Multiplizieren von dreidimensionalen Matrizen).
Wichtige Erkenntnis 2: Es gibt aber auch (präzise definierte, mathematische) Probleme, die man nicht
mit Hilfe einer solchen Turing-Maschine lösen kann.
Wichtige Vermutung 3: Alle Probleme, die man mit heutigen oder zukünftigen Computern lösen kann,
kann man im Prinzip auch mit einer Turing-Maschine lösen.
Im zweiten Weltkrieg arbeitete Turing für die Government Code and Cypher School in Bletchley Park
(d. h. für den britischen Geheimdienst) und half entscheidend dabei, die Maschine zu durchschauen, mit
der die deutsche Marine ihre Funksprüche verschlüsselte (die Enigma), und wichtige Funksprüche zu
entschlüsseln. Damit hat er vermutlich einer ganzen Reihe von alliierten Soldaten (Engländern, Amerikanern, Franzosen, Russen) das Leben gerettet.
Weil er homosexuell war, wurde Turing nach dem Krieg zu einer Hormonbehandlung "seiner Krankheit"
gezwungen, bekam schwere Depressionen und nahm sich das Leben. Inzwischen wurden die entsprechenden Gesetze in England (und ähnliche Gesetze in anderen Ländern) beseitigt. Im September 2009
entschuldigte sich der britische Premierminister Gordon Brown dafür, wie Turing behandelt worden ist.
Im Dezember 2013 wurde Turing von Queen Elizabeth "begnadigt" (he got a royal pardon).
2014 kam die "dramatisch zugespitzte Filmbiografie Turing's "The Imitation Game" heraus.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 23
Übung Ü-03
(Gruppe 1a am 07.05.2015,
Gruppe 1b am 21.05.2015,
Gruppe 1c am 30.04.2015)
1. Abnahme von Projekt 1 und 2
2. Lesen Sie im Papier TippsZuEclipse.pdf den Abschnitt
15. Suchen und Ersetzen mit regulären Ausdrücken und Fangmustern
und lösen Sie dann die Aufgabe am Anfang von S. 15:
Namen der Form "Otto Meier" oder "Asaf Yildirim" umwandeln in "Meier, Otto" bzw. "Yildirim, Asaf".
3. Das Projekt 3 (LongSpeicher30) fertig programmieren (mit der Programmierung haben wir
im SU 7 am 07.05.2015 begonnen).
S. 24, SS15
SU 8. Do 07.05.15, 3. Block
Beuth-Hochschule
SU 8. Do 07.05.15, 3. Block
Einstufige und mehrstufige Reihungen
Papier Buoys.pdf, S. 6 (Reihungen und mit primitiven und mit Referenz-Komponenten):
Example-01: Two arrays represented by buoys:
41
42
int[]
ap = {10, 20, 30};
String[] ar = {"AB", "C", "DEF");
// An array with primitive elements
// An array with reference elements
Die Bojen-Darstellung der Reihungen ap und ar macht deutlich:
1. Die Komponenten einer Reihung haben keine Namen (als Ersatz haben sie Indizes)
2. Die Referenzen und Werte der Komponenten gehören zur ("liegen innerhalb der") Reihung
3. Die Zielwerte von Komponenten gehören nicht zur Reihung ("liegen außerhalb der Reihung")
Wegen 3. ist es möglich, dass ein Objekt gleichzeitig zu mehreren Reihungen gehört
(siehe S. 7, Example-02)
In Java gibt es auch Reihungen-von-Reihungen. Eine solche Reihung-von-Reihungen enthält genau genommen aber keine Reihungen, sondern nur Referenz-Werte, die auf die Reihungen zeigen. Diese Komponenten-Reihungen können verschieden lang sein
(siehe S. 8 ganz unten Example-02 und S. 9 oben die Boje für die geschachtelte Reihung a2b).
Ein Zitat aus The Java Language Specification, Java SE 8 Edition, Seite 4
(siehe https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf):
"The language [Java] supports arrays of arrays, rather than multidimensional arrays".
Es ist nicht leicht, im Internet eine Erklärung des Unterschieds zwischen mehrstufigen Reihungen (nested arrays, arrays of arrays) und mehrdimensionalen Reihungen (multidimensional arrays) zu finden und
vielen Internet-Autoren scheint der Unterschied nicht klar zu sein. An sehr vielen Stellen werden die
mehrstufigen Reihungen von Java fälschlich als mehrdimensionale Reihungen bezeichnet.
Reihungen ausgeben
1
2
long[] r1 = {10, 20, 30};
pln(r1);
(pln ist auch hier ein Abkürzung für System.out.println). Was gibt dieser Befehl hier aus?
Das (vermutlich enttäuschende) Ergebnis: [J@1f26605
[
J
1f26605
bedeutet "Reihung von"
ist ein Codename für den primitiven Typ long
ist der sogenannte Hashcode des Objekts r1.
Hier ein anderer Befehl, mit dem man eine Reihung ausgeben kann:
3
pln(java.util.Arrays.toString(r1));
Das (vermutlich erfreuliche) Ergebnis: [10, 20, 30]
In der Datei AusgebenReihungen.java (auf meiner Netzseite) die Methoden
Arrays.toString und Arrays.deepToString ansehen und besprechen.
Zur Entspannung: Christian Morgenstern (1871-1914, München-Meran)
Anto-Logie
Im Anfang lebte, wie bekannt, als größter Säuger der Gig-ant. ...
Eine invertierte Evolution großer Tiere und Zahlen.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 25
Reihungen sortieren
Dieses Problem gehört zu den am intensivsten untersuchten algorithmischen Problemen,
für das sehr viele Lösungen entwickelt wurden.
Zur Erinnerung: Die wichtigsten Eigenschaften von Reihungen (engl. arrays)
Positive Eigenschaft: Der Zugriff auf eine beliebige Komponente r[i] benötigt sehr wenig Zeit, und
diese Zugriffszeit ist unabhängig von der Größe von i (ein Zugriff auf r[100_000] dauert nicht länger als ein Zugriff auf r[0] oder auf r[50_000] etc.).
Negative Eigenschaft: Reihungen "sind aus Beton" (ihre Länge ist nicht veränderbar).
Ein paar Grundideen zum Sortieren von Reihungen
int[] r = {20, 60, 40, 10, 50, 30}
Sortieren durch Vertauschen benachbarter Komponenten (Bubblesort):
Wenn zwei nebeneinander liegende Komponenten (z.B. r[0] und r[1] oder r[17] und r[18] etc.)
falsch-herum liegen, vertauscht man sie miteinander. Das macht man solange, bis alle Komponenten
richtig-herum liegen.
Zustand 0: 20 60 40 10 50 30 // 60-40, 60-10, 60-50, 60-30,
Zustand 1: 20 40 10 50 30 60 // 40-10, 50-30
Zustand 2: 20 10 40 30 50 60 // 20-10, 40-30
Zustand 3: 10 20 30 40 50 60
Die fett hervorgehobenen Komponenten liegen garantiert an ihrer "endgültigen Stelle".
Sortieren durch Auswahl (selection sort):
Man denkt sich die Reihung aus einem (bereits sortierten) Anfangsteil und
einem (noch nicht sortieren) Endteil bestehend.
Die Grenze | zwischen Anfangsteil und Endteil liegt
am Anfang: vor der 0-ten Komponenten (r[0])
am Ende:
vor der letzten Komponenten (r[r.length-1])
Bei jedem Schritt sucht man im Endteil die kleinste Komponente und vertauscht sie mit der ersten Komponente des Endteils.
Nach jedem Schritt gehört eine Komponente mehr zum Anfangsteil statt zum Endteil.
Zustand 0:|20 60 40 10 50 30 // r[0]=20 <-> r[3]=10
Zusatnd 1: 10|60 40 20 50 30 // r[1]=60 <-> r[3]=20
Zustand 2: 10 20|40 60 50 30 // r[2]=40 <-> r[5]=30
Zustand 3: 10 20 30|60 50 40 // r[3]=60 <-> r[5]=40
Zustand 4: 10 20 30 40|50 60 // r[4]=50 <-> r[4]=50 (kein Druckfehler!)
Zustand 5: 10 20 30 40 50|60
Sortieren durch Einfügen (insertion sort):
Man denkt sich die Reihung aus einem (bereits sortierten) Anfangsteil und
einem (noch nicht sortieren) Endteil bestehend.
Die Grenze | zwischen Anfangsteil und Endteil liegt
am Anfang: nach der 0-ten Komponenten (r[0])
am Ende:
nach der letzten Komponenten (r[r.length-1])
Bei jedem Schritt verschiebt man die erste Komponente des Endteils (um 0 oder mehr Positionen) so
weit nach links, bis sie "an der richtigen Stelle liegt".
Nach jedem Schritt gehört eine Komponente mehr zum Anfangsteil statt zum Endteil.
S. 26, SS15
Zustand
Zustand
Zustand
Zustand
Zustand
Zustand
SU 8. Do 07.05.15, 3. Block
0:
1:
2:
3:
4:
5:
20|60 40 10 50 30
20 60|40 10 50 30
20 40 60|10 50 30
10 20 40 60|50 30
10 20 40 50 60|30
10 20 30 40 50 60|
//
//
//
//
//
r[1]=60
r[2]=40
r[3]=10
r[4]=50
r[5]=30
<->
<->
<->
<->
<->
Beuth-Hochschule
r[1]=60
r[1]=60
r[0]=20
r[3]=60
r[2]=40
Aufgabe:
Sortieren Sie die Reihung String[] r = {"D", "B", "E", "A", "C"};
mit Papier und Bleistift nach den Algorithmen bubble sort, insertion sort und selection sort.
Lösungen zu der Aufgabe (Ausgabe des Programms Alg_Sort_BIS_T.java)
Alg_Sort_BIS_T: Jetzt geht es los!
------------------------------------------bubbleSort:
vor:
[D,
[D,
[B,
[B,
[A,
B,
B,
D,
A,
B,
E,
E,
A,
C,
C,
A,
A,
C,
D,
D,
C]
C]
E]
E]
E]
// D-B,E-A,E-C,
// D-A,D-C,
// B-A,
//
nach: [A, B, C, D, E] <--OK
----------------------------------------------insertionSort:
vor:
[D,
[D,
[B,
[B,
[A,
[A,
B,
B,
D,
D,
B,
B,
E,
E,
E,
E,
D,
C,
A,
A,
A,
A,
E,
D,
C]
C]
C]
C]
C]
E]
//
//
//
//
r[1]=B
r[2]=E
r[3]=A
r[4]=C
<->
<->
<->
<->
r[0]=D
r[2]=E
r[0]=B
r[2]=D
nach: [A, B, C, D, E] <--OK
----------------------------------------------selectionSort:
vor:
[D,
[D,
[A,
[A,
[A,
[A,
B,
B,
B,
B,
B,
B,
E,
E,
E,
E,
C,
C,
A,
A,
D,
D,
D,
D,
C]
C]
C]
C]
E]
E]
//
//
//
//
r[0]=D
r[1]=B
r[2]=E
r[3]=D
<->
<->
<->
<->
r[3]=A
r[1]=B
r[4]=C
r[3]=D
nach: [A, B, C, D, E] <--OK
----------------------------------------------Anzahl Tests: 3, davon Fehler: 0
------------------------------------------Alg_Sort_BIS_T: Das war's erstmal!
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 27
SU 9. Do 21.05.15, Block 1
Test 3 (Sie dürfen die Abkürzungen pln und printf verwenden. Falls der Platz auf dem ausgeteilten
Blatt nicht reicht, Rückseite verwenden).
Einfügen in eine verkettete List
Ein Arbeitsblatt dazu verteilen. In 2-er-Gruppen sollen drei Elemente in eine anfangs leere verkettete
Liste eingefügt werden. Das Ergebnis soll als Boje dargestellt werden. Die Methode fuegeEin findet
man aus S. 22 dieser Datei (Stichworte.pdf).
Algorithmen und Programme, Gemeinsamkeiten und Unterschiede
Was ein Java-Programm ist, ist sehr genau definiert. Wenn man in einem formal korrekten Programm
(ein Programm, das vom Ausführer akzeptiert wird) nur ein einziges Zeichen ändert, wird dadurch die
Bedeutung des Programms ("das, was es macht") geändert, oder der Ausführer akzeptiert es nicht mehr.
Was ein Algorithmus ist, ist nur sehr vage definiert. Algorithmen werden in verschiedenen Sprachen beschrieben, in natürlichen Sprachen (wie Deutsch, Englisch, ...) und in mehr oder weniger formalen Sprachen (z.B. in Programmiersprachen oder in sogenannten Pseudo-Code-Sprachen). Es gibt kein Programm, welches von einem Text zuverlässig feststellen könnte, ob er einen Algorithmus beschreibt oder
nicht.
Selbst wenn man einen Algorithmus z.B. durch ein Java-Programm beschreibt, gibt es wichtige Unterschiede zwischen dem konkreten Programm und dem abstrakten Algorithmus:
Beispiel-01: Ein Sortier-Programm und ein Sortier-Algorithmus
1
2
3
4
5
6
7
8
static void selectionSort(String[] r) {
if (r.length<=1) return;
for (int abHier=0; abHier<=r.length-2; abHier++) {
tausche_sel(r, abHier, indMin_sel(r, abHier));
}
}
Liest man diese Zeilen als Programm dann gilt u.a.:
Die Reihung r kann höchstens etwa 2.15 Milliarden String-Komponenten enthalten.
Jede Komponenten r[i] kann höchstens etwa 2.15 Milliarden char-Komponenten enthalten.
Es gibt etwa 65 Tausend verschiedene char-Werte.
...
Liest man die selben Zeilen als Algorithmus, dann nimmt man gewöhnlich an:
Die Reihung r kann beliebig viele (aber nur endlich viele) String-Komponenten enthalten.
Jede Komponente r[i] kann beliebig viele (aber nur endlich viele) char-Komponenten enthalten.
Wie viele verschiedene char-Werte es gibt, ist unwichtig.
...
Man sieht: Mit dem Algorithmus selectionSort kann man unendlich viele Reihungen sortieren, mit
dem Programm selectionSort nur endlich viele.
Häufig ergänzt man eine Programmiersprache auch um Typen, Methoden und andere Konstrukte, die es
in dieser Sprache eigentlich nicht gibt.
Beispiel-02: Wenn man Algorithmen in Java beschreibt ist es häufig günstig, sich einen primitiven Typ
nat (für natürliche Zahlen) dazu zu denken oder einen Typnamen Irgend, der für irgend einen Typ
steht, etc. Der Algorithmus selectionSort könnte dann einen Parameter vom Typ Irgend[] haben.
S. 28, SS15
SU 9. Do 21.05.15, Block 1
Beuth-Hochschule
Algorithmen und nicht-Algorithmen
Ein Algorithmus ist ein Verfahren, welches aus bestimmten Eingabedaten bestimmte Ausgabedaten erzeugt.
Wichtig ist: Einen Algorithmus muss man auf viele verschiedene Eingabedaten anwenden können. Im
Idealfall sollte die Menge der möglichen Eingabedaten unendlich sein.
Algorithmus oder nicht?
Ein Verfahren, mit dem man die ersten 10 Ziffern der Zahl pi berechnen kann?
(kein Algorithmus)
Ein Verfahren, mit dem man für jede natürliche Zahl n die n-te Ziffer der Zahl pi berechnen kann?
(ist ein Algorithmus)
Ein Verfahren, mit dem man Reihungen der Länge 10 von boolean-Werten sortieren kann?
(kein Algorithmus)
Ein Verfahren, mit dem man beliebig lange Reihungen von boolean-Werten sortieren kann?
(ist ein Algorithmus)
Wie kann man Algorithmen miteinander vergleichen?
Angenommen, wir haben zwei Algorithmen A1 und A2, die dasselbe algorithmische Problem lösen (z.B.
Reihungen sortieren). Wie können wir A1 und A2 miteinander vergleichen um herauszufinden, ob einer
der beiden deutlich schneller ist als der andere?
Vorgehensweise-1: Wir implementieren A1 und A2 z.B. durch Java-Programme P1 und P2, lassen sie
z.B. auf einem Windows Rechner z.B. mit einem Pentium-Prozessor Reihungen unterschiedlicher Länge
sortieren, Messen die benötigte Zeit und tragen sie in eine Tabelle ein.
Nachteil dieser Vorgehensweise? (Die Messergebnisse hängen wahrscheinlich nicht nur von den Algorithmen ab, sondern auch von der verwendeten Programmiersprache, dem Betriebssystem, der Hardware
etc. Außerdem ändern sich die Ausführungszeiten, wenn ein neuer Prozessor oder eine neue Betriebssystem-Version herauskommt).
Frage: Wie können wir etwas über den Zeitbedarf eines abstrakten Algorithmus herausfinden, was möglichst unabhängig ist von bestimmten Programmiersprachen, Betriebssystemen und und Prozessoren?
Im Allgemeinen wird der Zeitbedarf eines Algorithmus von der Größe des bearbeiteten Problems (d.h.
von der Länge der Eingabe) abhängen. Beispiel: Im Allgemeinen wird das Sortieren einer kurzen Reihung weniger Zeit kosten, als das Sortieren einer langen Reihung. Wir fragen uns deshalb:
Wie hängt der Zeitbedarf des Algorithmus von der Größe des bearbeiteten Problems ab?
Vorgehensweise-2: Wir untersuchen den Text des Algorithmus und versuchen herauszufinden: Wie viele
Schritte müssen ausgeführt werden, wenn man nach diesem Algorithmus ein Problem der Größe N bearbeitet? Wie hängt die Schrittzahl ab von der Problemgröße N?
Kernfrage: Was ist ein Schritt? (Beim Analysieren von Algorithmen, nicht beim Wandern!)
Def.: Ein Schritt ist eine Befehlsfolge, von der es plausibel ist anzunehmen, dass ihre Ausführungszeit
immer etwa gleich groß ist oder zumindest eine bestimmte feste Zeit nicht überschreitet.
Insbesondere darf die Ausführungszeit für einen Schritt nicht von der Problemgröße N (von der Länge
der Eingabe) abhängen.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 29
Konkrete Beispiele für Schritte und nicht-Schritte:
Auch hier soll N die Größe des zu lösenden Problems (die Länge der Eingabe) bezeichnen.
Beispiele: Bei Addier-Algorithmen ist N die Länge der zu addierenden Zahlen. Bei Sortier-Algorithmen
ist N die Länge der zu sortierenden Reihung, etc.
Befehlsfolge
Ein Schritt? Begründung
1 Addition von zwei int-Werten
ja
500 Additionen von je zwei int-Werten
ja
N Additionen von je zwei int-Werten
1 Vergleich von zwei char-Werten
1 Vergleich von zwei String-Objekten
500 Vergleiche von String-Objekten, die
höchstens 100 Zeichen lang sind
nein
ja
nein
nein
500 Additionen von BigInteger-Objekten,
die weniger als 100 int-Variablen
enthalten.
ja
N Additionen von BigInteger-Objekten, die
weniger als 100 int-Variablen enthalten
nein
N Schritte
Ein String-Objekt kann bis zu
2,15 Milliarden char-Werte enthalten
ja
1 Addition von zwei BigInteger-Objekten
500 Schritte
abhängig von Problemgröße N
Ein BigInteger-Objekt kann bis zu
2,15 Milliarden int-Variablen enthalten
abhängig von Problemgröße N
ja
nein
abhängig von Problemgröße N
Der Begriff eines Schrittes kann einem anfangs widersinnig vorkommen (z.B. weil man 500 Schritte
auch als 1 Schritt zählen kann). Kernidee: Konstante Faktoren (3*N oder 500*N) sind unwichtig, Unterschiede zwischen Funktionen wie N und N2 und 2N etc. sind wichtig.
Zur Entspannung: Charles Babbage (1791-1871)
Forschte auf verschiedenen Gebieten. Unternahm mehrere Versuche, mechanische Rechenmaschinen zu
bauen. Keine davon wurde funktionstüchtig, aber seine Pläne und Überlegungen dazu waren wichtige
Stationen auf dem Weg zu Computern.
1823 Difference Engine no. 1: In die Entwicklung flossen 17.000 Pfund der britischen Regierung, was
etwa dem Preis von zwei Schlachtschiffen entsprach. Dann brach die Regierung das Projekt ab.
1833 Analytical Engine: Die sollte sogar schon programmierbar werden und Lochkarten lesen.
1847 Difference Engine no. 2: Verbesserte Variante der Difference Engine no. 1.
1985 Die Difference Engine no. 2 wird im Science Museum in London nach den Plänen von Babbage
gebaut (das Rechenwerk war 1991 fertig, das Druckwerk 2002) und funktioniert.
2012 Es gibt einen Plan, auch die Analytical Engine zu bauen (siehe http://plan28.org/).
Ada Byron, Lady Lovelace (1815-1852), Tochter des berühmten Dichters Lord Byron, arbeitete mit an
der Analytical Engine und gilt seitdem als erste Programmiererin. Nach ihr ist die Sprache Ada benannt
(ANSI/MIL-STD-1815, nach ihrem Geburtsjahr).
Weitere Erfindungen von Charles Babbage: Kuhfänger (für Lokomotiven, z. B. im Wilden Westen). Er
knackte als erster eine Vignére-Verschlüsselung (die vorher als sicher galt). Schrieb das Buch Economy
of machinery and manufactures, eine Analyse des Frühkapitalismus und wichtige Quelle für Karl Marx.
S. 30, SS15
SU 9. Do 21.05.15, Block 1
Beuth-Hochschule
Ü-03 , Do 21.05.15, 2. Block (Gruppe 1b, siehe Seite 23).
SU 10. Do 21.05.15, 3. Block
Das Papier TildeUndGrossO.pdf besprechen
Was ist ein Algorithmus? (S. 1)
Der Algorithmus von Euklid (Original, auf Deutsch, Pseudocode, Java-Methoden, S. 1-2)
Anmerkung: euklidMO und euklidR (auf S. 2 des Papiers) sind zwei deutlich verschiedene JavaMethoden. Ob sie denselben Algorithmus oder zwei verschiedene Algorithmen darstellen, ist nicht klar
definiert ("Ansichtssache"). Auch das ist ein wichtiger Unterschied zwischen Programmen (einer genau
definierten Programmiersprache) und Algorithmen.
Eigenschaften von abstrakten Algorithmen (S. 3)
Sich schnell ändernde Eigenschaften (z.B. von Programmen) und
"haltbare" Eigenschaften (z.B. von Algorithmen).
Was ein Schritt ist haben wir schon besprochen.
Schrittzahl, Tilde und Groß-O-Notation
S. 4: Wir analysieren einen (durch eine Java-Methode dargestellten) Algorithmus alg01
Lösung-01: Bei welchen der 5 Schleifen hängt die Anzahl der Rumpfausführungen von
der Problemgröße N ab (bei S11, S12 und S22) und bei welchen nicht (bei S13 und S21)?
Lösung-02: Wie oft werden die Methoden schritt1 und schritt2 ausgeführt, wenn der Algorithmus alg01 auf eine Reihung r der Länge N angewendet wird?
3 * N2 schritt1 + 50 * N schritt2
Lösung-03: Angenommen wir wissen, dass ein schritt2-Schritt etwa 20 mal so viel Zeit braucht, wie
ein schritt1-Schritt. Vereinfachen Sie Ihre Lösung für Aufgabe-02 entsprechend, so dass dort nur
noch schritt1 (aber nicht mehr schritt2) vorkommt.
3 * N2 + 1000 * N
schritt1
Lösung-04: Füllen Sie die leeren Felder der folgenden Tabelle aus:
Spalt 1
Spalte 2
Spalte 3
2
Spalte 4
2
N
1_000 * N
3*N
3 * N + 1_000 * N
100
100_000
30_000
130_000
10_000
10_000_000
300_000_000
310_000_000
1_000_000
1_000_000_000
3_000_000_000_000
3_001_000_000_000
Lösung-05: Ungefähr wie viel Prozent macht das Glied 1_000 * N (in Spalte 2)
an der Gesamtschrittzahl (in Spalte 4) aus,
wenn N gleich 10_000 ist (Zeile 2)?
(Etwa 3,3 Prozent).
Und wenn N gleich 1_000_000 ist (Zeile 3)? (Etwa 0,3 Promille).
Wenn man in der Formel 3*N2 + 1_000*N den zweiten Summanden (1_000*N) weglässt, macht
man einen "Fehler". Die Aufgaben -04 und -05 sollen deutlich machen, dass dieser "Fehler" für große N
vernachlässigbar klein ist (mit 0,3 Promille dürfte man sogar noch Auto fahren :-).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 31
Tilde- und Groß-O (S. 5)
Der Algorithmus alg01 hat eine Zeitkomplexität von O(N2) (sprich: oh von enn quadrat).
Was bedeuten bestimmte Zeitkomplexitäten anschaulich? (Tabelle auf S. 7)
Lösung-06: Füllen Sie die leeren Felder aus:
Angenommen
die Funktion f(n) wächst wie
Das bedeutet: f(n) wächst ungefähr auf das 2-fache
wenn man n um folgenden Faktor vergrößert:
die 2-te Wurzel von n (Quadratwurzel)
22 gleich 4
die 3-te Wurzel von n (Kubikwurzel)
23 gleich 8
die 4-te Wurzel von n
24 gleich 16
die m-te Wurzel von n
2m
Lösung-07: Füllen Sie die leeren Felder aus:
Angenommen
die Funktion f(n) wächst wie
Das bedeutet: Wenn man n ver-2-facht, dann
wächst f(n) ungefähr um den folgenden Faktor:
die 2-te Potenz von n (d.h. wie n2)
22 gleich 4
die 3-te Potenz von n (d.h. wie n3)
23 gleich 8
die 4-te Potenz von n (d.h. wie n4)
24 gleich 16
die m-te Potenz von n (d.h. wie nm)
2m
Tipp: Lesen Sie die Lösungen -06 und -07 (insbesondere die fett gedruckten Spalten-Überschriften) an
mindestens 3 Tagen jeweils 5 bis 10 Minuten durch (besser noch: an 6 verschiedenen Tagen).
Zur Entspannung: Ein Blatt Papier 50 Mal halbieren und stapeln
Stellen Sie sich vor: Wir haben ein großes Blatt Papier (z.B. eine Blatt der Zeitung "Die Zeit"). Wir reißen oder schneiden das Papier in zwei Hälften und legen die beiden Hälften übereinander. Dann reißen
oder schneiden wir diesen kleinen Stapel ebenso in zwei Hälften und legen sie übereinander, dann reißen oder schneiden wir diesen Stapel ebenso in zwei Hälften etc. etc. Insgesamt wiederholen wir diesen
Vorgang 50 Mal. Wie hoch ist der Papierstapel am Ende ungefähr?
Tabelle mit 2-er- und 10-er-Potenzen, die sich ungefähr entsprechen:
210
103
1 Tausend
220
106
1 Million
230
109
1 Milliarde
240
1012
1 Billion
250 Schichten Zeitungspapier sind etwa gleich
1015 Schichten Zeitungspapier (siehe Tabelle).
Angenommen, 10 Schichten sind 1 mm dick. Dann gilt:
1 mm
10 Schichten
1m
10 000 Schichten
1 km
10 000 000 Schichten (d.h. 107 Schichten)
15
7
10 / 10 ist gleich 108 gleich 100 Millionen km
250
1015
1Billiarde
260
1018
1 Trillion
S. 32, SS15
SU 10. Do 21.05.15, 3. Block
Beuth-Hochschule
Ü1c-03, Do 28.05.15, Block 1, siehe S. 23
Ü1a-04, Do 28.05.15, Block 2
Abnahme der Projekte 1 bis 4. Persönlich Anwesenheit erforderlich.
SU 11. Do 28.05.15, Block 3
Vereinfachte Bojen-Darstellung von Reihungen und anderen Objekten
Die Komponenten von Reihungen sind Variablen. Diese Variablen bestehen aus einer Referenz und einem Wert. Sie haben keinen Namen, nur einen Index (der ohne Paddelboot notiert wird).
Wenn man Bojen zeichnet darf man Reihungen vereinfacht darstellen (siehe Papier JavaBuoys.pdf,
S. 7, "Note: In Example-02 the references of the array-elements and the length-variables have been omitted.").
Achtung: Nur die Referenzen der Reihungskomponenten (array-elements) darf man weglassen. Die Referenzen von Reihungsvariablen darf man nicht weglassen.
Entsprechendes gilt für Objekte, die Attribute (Variablen) enthalten. In den Projekten 3 und 4 kommen
Knoten-Objekte vor. Jedes solches Objekt enthält 2 Variablen (namens next und data). Die Referenzen dieser Variablen (und das Paddelboot für den Namen) darf man weglassen.
Im Buch "Java ist eine Sprache" wird der Unterschied zwischen der vollständigen und vereinfachten
Darstellung von Bojen genauer erklärt (siehe S. 156 - 158).
Schrittfunktionen von Algorithmen ermitteln
Öffnen Sie die Datei SchrittfunktionenA.java und programmieren Sie für die Algorithmen
alg01 bis alg05 entsprechende Schrittfunktionen stp01 bis stp05.
Zusammenhang zwischen einem Algorithmus alg und seiner Schrittfunktion stp:
Wenn die Ausführung des Aufrufs
alg(17) z.B. 238 Schritte erfordert, dann soll der Aufruf
stp(17) als Ergebnis 238 liefern.
Der Gauß-Trick zum Addieren bestimmter Folgen von ganzen Zahlen
"(Erste Zahl plus letzte Zahl) mal Anzahl der Paare"
Die Summe der Zahlen 1, 2, 3, ... 10 ist gleich (1+10)*5
= 55
Die Summe der Zahlen 1, 2, 3, ... 11 ist gleich (1+11)*5,5 = 66
Der gleiche Trick funktioniert auch dann, wenn die Zahlenfolge bei einer größeren Zahl als 1 beginnt
oder der Abstand zwischen zwei Zahlen größer als 1 ist:
Die Summe der Zahlen 11, 12, 13, ..., 30 ist gleich (11+30)*10 = 410
Die Summe der Zahlen 3, 6, 9, ..., 30 ist gleich ( 3+30)* 5 = 165
Schrittfunktionen von Algorithmen ermitteln (Fortsetzung 1)
Entwickeln Sie die Schrittfunkton stp06 bis stp09 (für die Algorithmen alg06 bis alg09)
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 33
Zur Entspannung: Der EPR-Effekt
Albert Einstein mochte die Quantenmechanik nicht. Er dachte sich mehrere Gedankenexperimente aus,
die zeigen sollten, dass sie fehlerhaft ist oder zumindest "keine vollständige Beschreibung der Natur"
liefert. Nils Bohr vertrat die Quantenmechanik und fühlte sich zuständig für ihre Verteidigung. Mehrmals gelang es ihm, in einem Gedankenexperiment von Einstein einen subtilen Fehler zu entdecken und
die Argumente von Einstein dadurch zu entkräften. Bei einem der Gedankenexperimente gelang ihm das
aber nicht.
Einstein mochte die Quantenmechanik nicht, kannte sie aber offenbar so genau, dass er auch einige ihrer
entfernten Konsequenzen erkennen konnte. Den Effekt, der heute als EPR-Effekt bezeichnet wird (nach
Einstein, seinem Physiker-Kollegen Podolski und einem Studenten Rosen) ist eine Konsequenz der
Quantenmechanik, die Einstein "so unsinnig und unglaubhaft" vorkam, dass er sie als Argument gegen
die Quantenmechanik veröffentlichte. Inzwischen hat man diesen merkwürdigen Effekt experimentell
nachgewiesen und benutzt ihn zur abhörsicheren Übertragung von Daten.
Parameter-Übergabe-Mechanismen
Kennen Sie die Begriffe "Parameter" und "Argument"?
Oder die Begriffe "formaler Parameter" und "aktueller Parameter"?
Was muss bzw. darf ein Programmierer mit einer Methode machen?
(Er muss sie zuerst einmal vereinbaren, dann darf er sie beliebig oft aufrufen).
Parameter kommen in Vereinbarungen von Methoden vor.
Argumente kommen in Aufrufen von Methoden vor.
Öffnen Sie bitte das Papier ParameterUebergabe.pdf (4 Seiten).
Beispiel-01 und Beispiel-02 besprechen.
In Java gibt es nur einen Parameter-Übergabe-Mechanismus: Übergabe per Wert. (Def. besprechen)
In anderen Sprachen gibt es weitere Mechanismen, z.B. Übergabe per Referenz. (Def. besprechen)
Was geht nicht mit Übergabe per Wert?
Man kann einer Methode nicht eine Variable v übergeben, sozusagen mit der Bitte: "Ändere mir mal den
Wert dieser Variablen".
Nur mit Übergabe per Wert ist das Projekt 6 ein bisschen schwieriger zu programmieren (mit Übergabe
per Referenz würde es ein bisschen einfacher und eleganter gehen).
S. 34, SS15
SU 12. Do 04.06.15, Block 1
Beuth-Hochschule
SU 12. Do 04.06.15, Block 1
Test 4
Parameter-Übergabe-Mechanismen (Fortsetzung und Ende)
Im Papier ParameterUebergabe.pdf auf S. 1 den Kasten zu Übergabe per Wert ansehen.
Wie man sich "Übergabe per Wert" vorstellen kann: Bei jedem Aufruf einer Methode (z.B. der Methode
machWas) wird die erste Zeile der Methoden-Vereinbarung verändert, so dass die Parameter mit den
Werten der Argumente initialisiert werden.
Auf S. 2 den Kasten Übergabe per Referenz ansehen.
Was kann man mit Übergabe per Wert nicht machen? (siehe S. 2 Mitte)
Im Projekt 5 (binäre Bäume) werden wir Übergabe per Referenz "vermissen" und "selbst nachbauen".
Schrittfunktionen von Algorithmen ermitteln (Fortsetzung 2)
Die Hilfsmethoden h ("hoch"), glA ("ganzzahliger Logarithmus a") und glB kurz besprechen.
Schritt-Tabelle für alg09:
n
1
2
3
4
5
6
7
Schritte
1
2
3
4
5
6
7
static public int stp09(int n) {return n;}
Schritt-Tabelle für alg10:
n
1
2
3
4
5
6
7
Schritte
1
3
7
15
31
63
127
static public int stp10(int n) {return h(2, n)-1;}
Schritt-Tabelle für alg11:
n
1
2
3
4
5
6
7
Schritte
1
4
13
40
121
364
1_093
static public int stp11(int n) {return h(3, n) / 2;}
Schritt-Tabelle für alg12:
n
1
2
3
4
5
6
7
Schritte
1
5
21
85
341
1_365
5_461
static public int stp12(int n) {return h(4, n) / 3;}
Schritt-Tabelle für alg13:
n
1
2
3
4
5
6
7
Schritte
1
2
4
8
16
32
64
static public int stp13(int n) {return h(2, n-1);}
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 35
Schritt-Tabelle für alg14:
n
1
2
3
4
5
6
7
Schritte
1
3
9
27
81
243
729
static public int stp14(int n) {return h(3, n-1);}
Schritt-Tabelle für alg15:
n
1
2
3
4
5
6
7
Schritte
1
2
2
3
3
3
3
static public int stp15(int n) {return glB(2, n);}
Schritt-Tabelle für alg16:
n
1
2
3
4
5
6
7
Schritte
1
1
2
2
2
2
2
static public int stp16(int n) {return glB(3, n);}
Schritt-Tabelle für alg17: (Ziemlich schwierig!)
n
1
2
3
4
5
6
7
Schritte
1
4
8
12
17
22
27
static public int stp17(int n) {
int logN
= glB(2, n);
int max2erPotenzKleinerN = h(2, logN-1);
int korrektur
= 2 * (n - max2erPotenzKleinerN);
// Die korrektur ist immer kleiner als n
return n * logN + korrektur;
}
Zur Entspannung: Eigenschaften von Qubits (Quanten-Bits)
1. Mit n "normalen Bits" kann man eine Zahl (zwischen 0 und 2n-1) darstellen. Mit n Qubits kann man
gleichzeitig bis zu 2n Zahlen (zwischen 0 und 2n-1) darstellen und mit einer Operation kann man alle
diese Zahlen "gleichzeitig bearbeiten".
Angenommen wir haben einen Speicher S, der aus 20 Qubits besteht. Dann können wir darin etwa 1
Million Zahlen (zwischen 0 und etwa 1 Million) speichern und mit einer Operation all diese Zahlen auf
einmal verändern. Wenn S aus 30 Qubits besteht, gilt alles entsprechend, aber mit 1 Milliarde Zahlen,
und bei 40 Qubits mit 1 Billion Zahlen etc.
2. Wenn man unseren Speicher S "ansieht und ausliest", bekommt man allerdings nur eine der Zahlen,
die sich im Speicher befinden. Die übrigen Zahlen gehen dabei unvermeidbar und unwiderruflich verloren. Während mit unserem Speicher S gerechnet wird, muss der Speicher deshalb sorgfältig von der
Umwelt isoliert werden, denn fast jede Interaktion des Speichers mit der Umwelt zählt als "ansehen und
auslesen".
3. Es ist nicht möglich, ein Qubit (mit all seinen Werten) zu kopieren. Man kann höchstens einen seiner
Werte kopieren (und die übrigen Werte gehen dabei verloren).
4. Auf Qubits kann man nur umkehrbare Verknüpfungen anwenden.
Zur Zeit (2008) erforschen mehrere Tausend Physiker, Informatiker und Ingenieure in mehr als 100 Forschungsgruppen etwa ein Dutzend Möglichkeiten, Qubits zu realisieren (durch ion traps, quantum dots,
linear optics, ...).
S. 36, SS15
SU 12. Do 04.06.15, Block 1
Beuth-Hochschule
Eine interessante Einführung in die Quantenmechanik. Die Autorin war Schülerin an einem Berliner
Gymnasium, als sie dieses Buch schrieb:
Silvia Arroyo Camejo: "Skurrile Quantenwelt", Springer 2006, Fischer 2007
Ü1b-04, Do 04.05.15, Block 2: Abnahme Projekt 1 bis 4
SU 13. Do 04.06.15, Bock 3
Zwei Arten von Programmiersprachen
Prozedurale Sprachen (haben veränderbare Variablen, die Zuweisungs-Anweisung, Funktionen und
Prozeduren), z.B. Fortran, Cobol, Pascal, Ada, Java, C#, JavaScript, ...
Funktionale Sprachen (haben nur unveränderbare Variablen, keine Zuweisung, keine Prozeduren, nur
Funktionen), z.B. Lisp, Scheme, Miranda, Opal, Haskell, ...
Zum "funktionalen Programmierstil" gehört es, dass man häufig Funktionen vereinbart und aufruft, die
Funktionen als Argumente erwarten.
In Java war das möglich, aber ziemlich umständlich und mühsam: Man musste die Methoden, die man
als Argumente übergeben wollte, in ein Objekt "einwickeln", und vorher musste man den Typ dieses Objekts, d.h. seine Klasse, vereinbaren. Erst mit Java 8 ist es für den Programmierer (nicht für den Ausführer) leichter geworden, Methoden als Argumente an eine Methode zu übergeben, und zwar in Form von
sogenannten Lambda-Ausdrücken. Beispiele:
n -> 3*n + 5
(n1, n2) -> 3*n1 - 2*n2
name -> println("Hallo " + name)
() -> println("Hallo Welt!")
//
//
//
//
Eine
Eine
Eine
Eine
Funktion
Funktion
Prozedur
Prozedur
mit
mit
mit
mit
einem
zwei
einem
null
Parameter n
Parametern n1, n2
Parameter name
Parametern
Die Typen der Parameter müssen aus dem Zusammenhang folgen. Durch solche Lambda-Ausdrücke
wurde der "funktionale Teil" von Java deutlich verstärkt.
Empfehlung: Lernen Sie möglichst bald auch eine funktionale Sprache kennen. Im Fach Compilerbau
(für den Studiengang TI-B) wird die funktionale Sprache Gentle benutzt.
Anmerkung zu den Projekten 1 bis 6
In den Klausuren (Hauptklausur und Nachklausur) wird vorausgesetzt, dass Sie mit allen Einzelheiten
dieser 6 Projekte gut vertraut sind. Insbesondere sollten Sie alle Aufgaben, die zu den einzelnen Projekten gehören (und in der Datei Projekte.pdf stehen), lösen können.
Vergleich sortierte Reihungen und sortierte Listen (Projekte 2 und 4)
Was ist bei sortierten Reihungen viel besser als bei sortierten Listen?
(Das binäre Suchen bei sortieren Reihungen ist viel schneller als das Suchen in Listen).
Was ist bei sortierten Listen besser als bei sortierten Reihungen?
(Listen sind flexibel, wir sagen auch: "sie sind aus Gummi", Reihungen sind "aus Beton").
Es wäre doch schön, wenn man die Vorteile von sortierten Reihungen (das binäre Suchen) und von sortierten Reihungen (die Flexibilität) kombinieren könnte.
Das ist tatsächlich möglich, mit binären Bäumen.
In der Datei Projekte.pdf, Projekt 5: Sammeln in einem binären Baum, S. 15
S. 15: Def.: Binärer Baum
S. 15: Def.: Ein binärer Baum ist sortiert wenn ...
S. 15: Def.: Tiefe eines binären Baums
Die Knoten bilden Ebenen, die wir (von oben nach unten) mit 0 beginnend nummerieren (ganz ähnlich
wie in Java die Komponenten einer Reihung mit 0 beginnend nummeriert sind).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 37
Die Tiefe des Baumes gibt an, wie viele Ebenen es gibt
(entspricht der Länge r.length einer Reihung r) .
Wie viele Knoten gibt es (höchstens) auf Ebene 0? Auf Ebene 1? Auf Ebene 2? Auf Ebene h? (2h)
Wie viele Knoten hat ein Baum der Tiefe t mindestens? (t Knoten)
Wie viele Knoten hat ein Baum der Tiefe 1 höchstens? Der Tiefe 2? Der Tiefe 3? Der Tiefe t (2t - 1)
S. 17: Aufgabe-01 bis Aufgabe-06
Achtung: Zwei sortierte Reihungen mit gleichen Komponenten sehen genau gleich aus.
Zwei sortierte Bäume mit gleichen Komponenten können sehr verschieden aussehen.
Falls noch Zeit ist:
Angenommen, wir haben ein LongSpeicher50-Objekt erzeugen lassen:
LongsSpeicher50 s = new LongSpeicher50();
Wie sehen die Attribute s.AR und s.EDK als Bojen dargestellt aus?
Vervollständigen Sie die Methode refkR (Datei Projekte.pdf, S. 16, unten)
Zur Entspannung: Christian Morgenstern (1871-1914, München-Meran)
Tertius Gaudens ("Da freut sich der Dritte")
Vor vielen Jahren sozusagen, hat folgendes sich zugetragen:
Drei Säue taten um ein Huhn / in einem Korb zusammen ruhn.
...
S. 38, SS15
SU 13. Do 04.06.15, Bock 3
Beuth-Hochschule
Ü1c-04, Do 11.06.15, Block 1
Ü1a-05, Do 11.06.15, Block 2
Test31 (Do 11.06.15, 11.30 Uhr im Raum DE17)
SU 14. Do 11.06.15, 3. Block
Binäre Bäume (Fortsetzung)
Was ist ein binärer Baum (entweder .... oder ...)?
Wann ist ein binärer Baum sortiert?
Aufgabe-01: Fügen Sie folgende Schlüssel in der angegebenen Reihenfolge in einen anfangs leeren binären Baum ein: 90, 30, 60, 80, 70, 75
Aufgabe-02: Ebenso: 10, 20, 30, 40, 50, 60
Die Reihenfolge, in der die einzelnen Schlüssel eingefügt werden ist sehr wichtig. Bei gewissen Reihenfolgen entartet der Baum und ist eventuell nicht besser (oder nicht viel besser) als eine verkettete Liste.
Welche Tiefe hat ein binärer Baum mit 100 Knoten höchstens? (100)
Wie viele Knoten hat ein binärer Baum der Tiefe 100 mindestens? (100)
Wie viele Knoten hat ein binärer Baum der Tiefe 10 höchstens (210-1 gleich 1023)
Knoten löschen in einem binären Baum
Wir sehen uns im Papier BinBaumBoje.pdf die S. 2 an (ein LongSpeicher50-Objekt mit 11 Knoten) und
gleichzeitig im Papier Projekte.pdf die S. 16 (den vorgegebenen Teil der Klasse LongSpeicher50).
1. Beschreiben Sie den Ziel-Wert der Variablen AR (Typ und "Inhalt" des Zielwertes).
(AR zeigt auf ein RefK-Objekt, welches nur 1 (Refernz-) Attribut k mit dem Wert [<140>] enthält.)
2. Von welchem Typ ist die Variable AR.k? (Vom Typ Knoten)
3. Beschreiben Sie den Ziel-Wert der Variablen AR.k (Typ, Anzahl und Werte der Attribute?)
(Typ Knoten, 3 Attribute data, lubr, rubr, Werte [45], [<150>], [<160>])
4. Wie viele Knoten-Objekte gibt es in dieser Abbildung insgesamt? 12
5. Wie viele davon sind "richtige Knoten-Objekte"? 11
6. Wie heißt das einzige "nicht-richtige" Knoten-Objekt? (s.EDK, End Dummy Knoten)
7. Wie viele RefK-Objekte gibt es in dieser Abbildung insgesamt?
23, 2 für jeden richtigen Knoten plus der Ziel-Wert der Variablen s.AR.
8. Welche Referenz soll der Aufruf refk(45) liefern? Die Referenz [<130>].
9. Welche Referenz soll der Aufruf refk(35) liefern? Die Referenz [<200>].
10. Welche Referenz soll der Aufruf refk(61) liefern? Die Referenz [<320>].
11. Welche Referenz soll der Aufruf refk(33) liefern? Die Referenz [<460>].
12. Welche Referenz soll der Aufruf refk(99) liefern? Die Referenz [<220>].
Beim Löschen von Knoten gibt es 4 verschiedene Fälle. Davon ist einer ganz einfach, zwei weitere sind
einfach, und nur der vierte Fall ist ein bisschen komplizierter.
In den folgenden Beispielen soll immer der Knoten mit dem Schlüssel 50 gelöscht werden.
Fall 1: Beide Unterbäume des zu löschenden Knotens sind leer (ganz einfach,
kann wahlweise wie Fall 2 oder wie Fall 3 behandelt werden).
Fall 2: Der linke Unterbaum des zu löschenden Knoten ist leer
Fall 3: Der rechte Unterbaum des zu löschenden Knoten ist leer
Beuth Hochschule
Stichworte zu Algorithmen
10
10
SS15, S. 39
10
50
50
10
50
70
70
50
30
30
Fall 2
Fall 3
Im Papier BinBaumBoje.pdf:
Fall 1: Welche Knoten haben 2 leere Unterbäume? (Die Knoten mit data 11, 23, 32, 52, 61)
Um den Knoten mit data 23 zu löschen: Den Wert welcher Variablen müssen wir wie verändern?
(eine RefK-Variable namens k, alter Wert [<360>], neuer Wert [<600>])
Um den Knoten mit data 52 zu löschen: Den Wert welcher Variablen müssen wir wie verändern?
(eine RefK-Variable namens k, alter Wert [<390>], neuer Wert [<600>])
Fall 2 oder 3: Welche Knoten haben 1 leeren Unterbaum? (Die Knoten mit data 35, 68)
Um den Knoten mit data 35 zu löschen: Den Wert welcher Variablen müssen wir wie verändern?
(eine RefK-Variable namens k, alter Wert [<240>], neuer Wert [<370>])
Um den Knoten mit data 68 zu löschen: Den Wert welcher Variablen müssen wir wie verändern?
(eine RefK-Variable namens k, alter Wert [<180>], neuer Wert [<250>])
Fall 4: Beide Unterbäume des zu löschenden Knotens L (mit Schlüssel 50) sind nicht leer
10
10
45
50
30
70
30
70
...
...
38
2. Knoten
löschen
1. Daten
kopieren
38
45
45
40
40
Fall 4
Schritt 4.1.: Wir gehen zum linken Unterbaum von L (der beginnt hier mit 30)
Schritt 4.2.: In diesem Unterbaum suchen wir den Knoten MAX mit dem größten Schlüssel (hier: 45)
Der rechte Unterbaum von MAX ist sicherlich leer (sonst würden darin ja Schlüssel stehen, die größer
sind als der Schlüssel von MAX. Aber dann wäre MAX nicht MAX).
Schritt 4.3.: Wir kopieren die Daten aus MAX in den Knoten L (in der Graphik: 45 -> 50)
Schritt 4.4.: Wir löschen den Knoten MAX (in der Graphik: den Knoten mit Schlüssel 45)
Anmerkung: Das Löschen von MAX ist ein Fall 3 oder ein Fall 1, also einfach oder ganz einfach.
S. 40, SS15
SU 14. Do 11.06.15, 3. Block
Beuth-Hochschule
Im Papier BinBaumBoje.pdf, S. 2:
Fall 4: Welche Knoten haben 0 leere Unterbäume, d.h. 2 nicht-leere-Unterbäume? (Die Knoten mit den
Schlüsseln 45, 27, 18, 57)
Was müssen wir machen, um den Knoten mit data 27 zu löschen?
1. data 23 nach data 27 kopieren
2. Knoten mit data 23 löschen ([<360>] durch [<600>] ersetzen)
Schreiben Sie jetzt (für das Projekt 5, LongSpeier50, die Methode loesche)
Tipp 1: Den Fall 1 brauchen wir nicht separat zu behandeln, sondern können ihn als Fall 2 oder Fall 3
behandeln lassen.
Tipp 2: In Rumpf von loesche sollten wir (wie fast immer) den einfachsten Fall zuerst behandeln.
Wann liegt dieser einfachste Fall vor? (Wenn der zu löschende long-Wert n in der Sammlung gar nicht
vorkommt).
Zur Entspannung: Die Polymerase Kettenreaktion (PKR, engl. PCR)
Wurde 1983 von Karry Mullis in Kalifornien (angeblich während einer langweiligen Autofahrt) erfunden. 1993 erhielt er den Nobelpreis dafür (obwohl er "nur eine Technik erfunden", aber keine "grundlegenden Prinzipien entdeckt" hatte).
Ein Polymer ist eine chemische Substanz, bei der die Länge der einzelnen Moleküle nicht genau festliegt, weil eine bestimmte Gruppe von Atomen ("ein Kettenglied") sich fast beliebig oft wiederholen
kann.
DNS-Moleküle (Desoxyribonukleinsäure) sind wichtige Beispiele für solche Kettenmoleküle. Ein DNSMolekül besteht aus zwei Teilsträngen (etwa wie Eisenbahnschienen), die aber nicht gleich, sondern
"Spiegelbilder voneinander" sind, etwa so:
ATGC ...
|||| ...
TACG ...
Eine Polymerase ist ein Enzym, welches z.B. DNS-Moleküle an einer bestimmten Stelle durchtrennen
kann, oder ähnliche chemische Reaktionen stark begünstigt. Z.B. gibt es eine Polymerase, mit der man
die beiden Teilstränge ("Eisenbahnschienen") von DNS-Molekülen voneinander trennen kann.
Die PKR ist eine Technik, mit der man DNS-Moleküle sehr schnell vermehren kann. Im Extremfall beginnt man mit einem einzigen DNS-Molekül und hat nach wenigen Stunden Milliarden oder Trillionen
Kopien davon.
Die PKR läuft in Schritten ab. Durch Erwärmen und Abkühlen der beteiligten Stoffe auf bestimmte
Temperaturen kann man die einzelnen Schritte einleiten bzw. beenden. Nach jeweils 3 solchen Schritten
hat sich die Anzahl der DNS-Moleküle verdoppelt. Diese drei Schritte dauern z.B. 5 Minuten. In 50 Minuten (ca. 1 Stunde) kann man also 10 Verdopplungen bewirken, die Anzahl der DNS-Moleküle also um
den Faktor 210 (ungefähr 1000) vermehren. Innerhalb von 6 Stunden kann man die Ausgangsmenge
theoretisch um einen Faktor von etwa 260 (≈ 1018 gleich eine Trillion) vermehren, praktisch ist die Ausbeute etwas geringer.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 41
SU 15. Do 18.06.15, Block 1
Test 5
Algorithmen anhand ihrer Zeitkomplexitäten vergleichen
Kurze Wiederholung:
Wir haben Algorithmen alg01, ... analysiert und dabei
ihre Schrittfunktionen stp01, ... ermittelt.
Aus den Schrittfunktionen haben wir die Zeitkomplexitäten der Algorithmen
in Groß-O-Notation ermittelt, z.B.
O(1), O(log(n)), O(√n), O(n), O(n*log(n)), O(n2), O(2n), O(n!), ...
Mit n ist hier immer die Problemgröße gemeint (z.B. die Länge der Reihungen, die sortiert werden sollen), und mit s die Anzahl der benötigten Schritte.
Was bedeutet die Zeitkomplexität O(n) anschaulich?
(Wenn man n ver-2-facht, dann ver-2-facht sich auch s,
wenn man n ver-3-facht, dann ver3-facht sich auch s ...)
Was bedeutet die Zeitkomplexität O(n2) anschaulich?
(Wenn man n ver-2-facht, dann ver-4-facht sich s,
wenn man n ver 3-facht, dann ver-9-facht sich s ...)
Was bedeutet die Zeitkomplexität O(√n) anschaulich?
(Wenn man n ver-4-facht, dann ver-2-facht sich s
wenn man n ver-9-facht, dann ver-3-facht sich s ...)
Was bedeutet die Zeitkomplexität O(log(n)) anschaulich?
(Wenn man n ver-2-facht, dann wird s um 1 größer)
Was bedeutet die Zeitkomplexität O(2n) anschaulich?
(Wenn man n um 1 vergrößert, dann ver-2-facht sich s)
Was bedeutet die Zeitkomplexität O(n*log(n)) anschaulich?
(s "wächst ein bisschen schneller" als bei O(n) z.B. so:
n
1 Tausend
1 Million
1 Milliarde
1 Billion
1 Billiarde
1 Trillion
...
n*log(n) 10 Tausend 20 Millionen 30 Milliarden 40 Billionen 50 Billiarden 60 Trillionen
...
Angenommen, wir haben zwei Algorithmen alg01 und alg02, die dasselbe algorithmische Problem
lösen (z.B. das Problem, Reihungen zu sortieren). Durch eine genaue Analyse haben wir festgestellt, dass
alg01 die Zeitkomplexität O(n2) und
alg02 die Zeitkomplexität O(n3) hat.
Was bedeutet das anschaulich?
alg02 braucht immer weniger Schritte als alg01? (Falsch)
alg01 braucht immer weniger Schritte als alg02? (Falsch)
Ab einer bestimmten Problemgröße n braucht alg01 immer weniger Schritte als alg02? (Richtig)
Ein typisches Beispiel: Es gibt viele Sortier-Algorithmen.
Einige sind ganz einfach,
und für kleine n ziemlich gut, werden aber für größere n immer schlechter.
Andere sind kompliziert,
und für kleine n ziemlich schlecht, werden aber für größere n immer besser.
S. 42, SS15
SU 15. Do 18.06.15, Block 1
Beuth-Hochschule
Binäre Bäume, abschließende Anmerkungen
Welche Gefahr droht bei binären Bäumen?
(Dass sie stark unbalanciert werden und dann nicht besser sind als Listen).
Es gibt verschiedene Möglichkeiten, das zu verhindern:
1. Man prüft bei jedem Einfügen und bei jedem Löschen, ob der Baum dadurch "unbalancierter" würde
und falls ja, "hängt man ein paar Unterbäume um", so dass das vermieden wird (siehe dazu z.B.
http://services.informatik.hs-mannheim.de/~schramm/ads/files/Kapitel10_02.pdf) .
2. Man verwendet kompliziertere Formen von Bäumen, z.B. 2-3-4-Bäume (bei denen jeder Knoten 2, 3
oder 4 Unterbäume hat und entsprechend 1, 2 bzw. 3 Schlüssel enthält) oder Rot-Schwarz-Bäume (die
Fraben dienen nur dazu, zwei Arten von Knoten zu unterscheiden).
3. Kompliziertere Bäume werden häufig durch binäre Bäume implementiert. Ein 3-er- oder 4-er-Knoten
eines 2-3-4-Baums wird dann durch mehrere Knoten eines binären Baums realisiert.
Was ist gut an Bäumen?
Suchen geht schnell ( O(log(n)) )
Einfügen geht schnell ( O(log(n)) )
Löschen geht schnell ( O(log(n)) )
Zur Entspannung: Mit DNS-Molekülen kombinatorische Probleme lösen
Die Gene aller Lebewesen bestehen aus DNS (Desoxyribonukleinsäure) Molekülen. Solche Moleküle
können große Mengen von Informationen auf sehr kleinem Raum speichern. Leonard M. Adleman hat
1994 zuerst gezeigt, dass man mit solchen Molekülen auch bestimmte algorithmische Probleme lösen
kann, z.B. das Problem des Handlungsreisenden (ein Handlungsreisender will n Städte besuchen und
sucht nach einem kürzesten Weg dafür). In ein Reagenzglas passen mehrere Trilliononen DNS-Moleküle, die (unter geeigneten Bedingungen) alle versuchen, sich miteinander zu verbinden. Mit DNS Ligase
kann man bestimmte Verbindungen erheblich erleichtern und damit beschleunigen.
Ein DNS-Moleküle besteht aus 2 Ketten von vier Nukleotiden: A, G, C, T. Ketten verbinden sich, wenn
sich überalle komplementäre Nukleotide gegenüberstehen, etwa so:
Kette 1: ACGT ...
||||
Kette 2: TGCA ...
Grundtechnik zur Lösung des Problems des Handlungsreisenden: Jede Stadt wird durch eine einfache
(nicht doppelte!) Kette von 20 Nukleotiden dargestellt, z.B. durch
Stadt A: TTGACGAATG ATGCTAGAAA (Komplement: AACTGCTTAC TACGATCTTT)
Stadt B: AATCCATGCG AAATTAGCCC (Komplement: TTAGGTACGC TTTAATCGGG)
Stadt C: TATGACCTAG CTAGCATAGC (Komplement: ATACTGGATC GATCGTATCG)
Eine Straße von Stadt x nach Stadt y wird ebenfalls durch 20 Nukleotide dargestellt: Die letzten 10 von
x und die ersten 10 von y. Hier zwei Straßen (von A nach B und von B nach C):
A-nach-B: ATGCTAGAAA AATCCATGCG
B-nach-C: AAATTAGCCC TATGACCTAG
Ein A-nach-B- Molekül kann sich mit dem Komplement von Stadt B verbinden wie folgt:
A-nach-B
: ATGCTAGAAA AATCCATGCG
||||||||||
Komplement von B :
TTAGGTACGC TTTAATCGGG
Dieses Molekül kann sich mit einer Straße B-nach-C verbinden:
A-nach-B, B-nach-C: ATGCTAGAAA AATCCATGCG AAATTAGCCC TATGACCTAG
|||||||||| ||||||||||
Komplement von B :
TTAGGTACGC TTTAATCGGG
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 43
Man erzeugt (mit der PKR) von jedem Städte-Molekül A, B, C, ... und von jedem Straßen-Molekül
A-nach-B, B-nach-C, ... ein paar Billiarden oder Trillionen, füllt alle Moleküle in ein Reagenzglas
und "schüttelt ein bisschen". Dann bilden sich u.a. Moleküle, die einem kürzesten Weg "an allen Städten
vorbei" entsprechen. Die kann man mit Standard-Techniken der Molekular-Biologie (Gel-Elektrophorese) "herausfiltern" und analysieren.
Ü1b-05, Do 18.06.15, Block 2
Die Projekte 1 bis 4 besprechen und abnehmen
SU 16. Do 18.06.15, Block 3
Das Projekt 6
In den Projekten 1 bis 5 haben wir Sammlungen auf 5 verschiedene Weisen implementiert, nämlich als?
(unsortierte Reihung, sortierte Reihung, unsortierte Liste, sortierte Liste, (sortierter) binärer Baum).
Alle diese Impelmentierungen werden heutzutage benutzt, keine ist in allen Anwendungsfällen "klar besser als alle anderen". Aber die 2-Bäume (so könnte man binäre Bäume auch bezeichnen) sind in vielen
Fällen sehr gut.
Kann man Sammlungen konstruieren, in denen man noch schneller suchen kann als in Bäumen?
Bitte öffnen Sie die Datei HashTabellen.pdf (5 Seiten).
Def. Hash-Tabelle
Ein ganz konkretes Beispiel: Ein Hash-Tabelle zum Sammeln von String-Objekten,
Länge der Hash-Tabelle 10, 14 Schlüssel sollen eingefügt werden
Verschiedene Hash-Funktionen:
hash01:
Schlechter geht es nicht
Aufgabe-01: 9 weitere schlechteste Hash-Funktionen (return 1, return 2, ...)
hash02:
hash03:
1 Bit des Schlüssels wird untersucht, 2 Listen werden benutzt, 8 bleiben leer
Das 0-te-Zeichen des Schlüssels wird untersucht, 5 Listen belegt, 5 leer
Aufgabe-02: Welche Buchstaben kommen in die gleiche Liste wie 'A' und 'K'? ('U')
hash032:
Das 2-te-Zeichen des Schlüssels wird untersucht, 8 Listen belegt, 2 leer
Aufgabe-04: Schlüssel für die hash03 gut ist ('F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', zu Hause?)
hash04:
hash05:
Mit "Bitfummelei", 8 Listen belegt, 2 leer.
Teuerere "Bitfummelei", 9 Listen belegt, 1 leer
Positive Eigenschaft 2: ("je länger die Hash-Tabelle, desto schneller")
Positive Eigenschaft 1: (Zeitkomplexität O(1))
hashCode() (guter "Anzug von der Stange", aber kein "Maßanzug")
Binäre Bäume (sind immer sortiert), Hash-Tabellen (sind nie sortiert, denn es gehört "zu ihrem
Wesen", dass die Schüssel zufällig oder chaotisch auf die einzelnen Listen verteilt werden).
Beispiele für Ergebnisse der Funktion (eigentlich: Funktionen) hashCode
Wenn noch Zeit ist: Projekt 6 (Hash-Tabelle) programmieren.
S. 44, SS15
SU 16. Do 18.06.15, Block 3
Beuth-Hochschule
Zur Entspannung: Ein Gedicht von Joseph von Eichendorff (1788-1857)
Um und nach 1800 entstand in Deutschland eine Bewegung zahlreicher Dichter und Philosophen, die
man heute als Romantik bezeichnet. Die Anhänger dieser Bewegung mussten sich unter anderem mit
den Auswirkungen der französischen Revolution und mit Napoleon auseinandersetzen. J. v. E. war ein
Adliger aus Oberschlesien, der seine Güter verlor und preussischer Beamter wurde.
Im Abendrot
Wir sind durch Not und Freude / gegangen Hand in Hand,
vom Wandern ruhen wir beide / nun überm stillen Land.
Rings sich die Täler neigen / es dunkelt schon die Luft,
zwei Lerchen nur noch steigen / nachträumend in den Duft.
Tritt her und laß sie schwirren / bald ist es Schlafenszeit,
daß wir uns nicht verirren / in dieser Einsamkeit.
O weiter, stiller Friede, / so tief im Abendrot!
Wie sind wir wandersmüde - / ist dies etwa der Tod?
Richard Strauss hat dieses Gedicht (1948, als letztes seiner "Vier letzten Lieder") vertont (siehe und
höre z.B. https://www.youtube.com/watch?v=co61XmUu-tc). Für den Film "I Dreamed of Africa" ("Ich
träumte von Afrika") hat Maurice Jarre (etwa im Jahr 2000) die Musik komponiert und arrangiert und
u.a. dieses Lied verwendet.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 45
Ü1c-05, Do 25.06.15, Block 1
Ü1a-06, Do 25.06.15, Block 2
Vor den Arbeiten an den Projekten 1 bis 6 sollen Sie sich mit Hilfe von zwei Java-Applets (namens
GleitBitFloatApplet und GleitBitDoubleApplet, ziemlich weit unten auf meiner Netzseite) mit Gleitpunktzahlen vom Type float und vom Typ double vertraut machen.
Als Vorbereitung müssen Sie Ihren Computer so einstellen, dass er das Ausführen der Applets erlaubt
(standardmäßig ist auf vielen Computern das Ausführen von Applets verboten).
So erlaubt man unter Windows, dass Java-Applets von einer vertrauenswürdigen Netzseite ausgeführt
werden:
Start-Knopf / Alle Programme / Java / Configure Java (oder: Java konfigurieren)
Dadurch sollte das Java Control Panel geöffnet werden.
Sicherheit / Siteliste bearbeiten
Unter Verzeichnis das betreffende Verzeichnis
(z.B. http://public.beuth-hochschule.de/~grude/)
eintragen und auf Hinzufügen klicken.
Falls es Ihnen nicht gelingt, die Applets auf auf Ihrem eigenen Rechner auszführen, dann benutzen Sie
bitte die Labor-Rechner (im Raum DE36/1)
Aufgabe-01: Untersuchen Sie mit Hilfe der Applets folgende Fragen:
Welchen Wert hat das float-Literal 0.1 (in einem Java-Programm: 0.1F)?
Welchen Wert hat das double-Literal 0.1 (in einem Java-Programm: 0.1D oder einfach 0.1)?
Ist der Wert von 0.1F kleiner oder größer als der Wert von 0.1D ?
Aufgabe-02: Öffnen Sie die Bedienungsanleitung des GleitBitFloatApplet's.
Gehen zu Abschnitt 4. Die Knöpfe Nächste float-Zahl und Vorige float-Zahl.
Folgen Sie den 3 Vorschlägen in diesem Abschnitt und beantworten Sie die Fragen:
Wie groß ist der Abstand zwischen der float-Zahl 4e6 und der nächsten float-Zahl?
Wie groß ist der Abstand zwischen der float-Zahl 16e6 und der nächsten float-Zahl?
Wie groß ist der Abstand zwischen der float-Zahl 16e9 und der nächsten float-Zahl?
S. 46, SS15
SU 17. Do 25.06.15, Block 3
Beuth-Hochschule
SU 17. Do 25.06.15, Block 3
Zeitkomplexitäten der Sortieralgorithmen bubble-, insertion- und selection-sort
Welche Zeitkomplexität (in groß-O-Notation) haben alle Varianten von bubblesort? (O(n2))
Raten Sie mal: Welche Zeitkomplexität haben insertionsort und selectionsort? (Ebenfalls O(n2)).
Was bedeutet O(n2)?
Faktor, um den sich
die Problemgröße n ändert
Faktor, um den sich
die benötigte Schrittzahl ändert
...
...
2
3
3 gleich 9
2
22 gleich 4
1
12 gleich 1
1/2
(1/2)2 gleich 1/4
1/3
(1/3)2 gleich 1/9
...
...
Eine wichtige Grundidee zur Beschleunigung von Algorithmen,
an einem ganz anderen Beispiel erläutert:
Stellen Sie sich vor: n Meter Draht kosten n2 Euro und wir brauchen 8 m.
Wie können wir es vermeiden, den hohen Preis von 82 gleich 64 Euro dafür zu bezahlen?
Wir kaufen 2 mal 4 m, die kosten nur 42 + 42 gleich 32 Euro.
Hinzu kommen allerdings noch die Kosten für das Zusammenschweißen der beiden 4-m-Stücke.
Wie können wir es vermeiden, für ein 4-m-Stück den hohen Preis von 16 Euro zu bezahlen?
Wir kaufen 2 mal 2 m, die kosten nur 8 Euro (plus das Zusammenschweißen).
Wie können wir es vermeiden, für ein 2-m-Stück den hohen Preis von 4 Euro zu bezahlen?
Wir kaufen 2 mal 1 m, die kosten nur 2 Euro (plus das Zusammenschweißen)
Wir wollen annehmen, dass 1 m die "Mindest-Abnahme-Menge" ist. Insgesamt kaufen wir also
8 mal 1 m für 8 Euro (und müssen die 8 Stücke dann zusammenschweißen).
Wenn das Zusammenschweißen nicht all zu teuer ist (z.B. 1 Euro pro Naht) lohnt sich das.
Ganz entsprechend beim Sortieren:
Wenn das Sortieren einer Reihung der Länge 8 ganze 82 (gleich 64) Schritte kostet, ist es es günstiger,
zwei Hälften der Länge 4 zu sortieren (in 42 + 42 gleich 32 Schritten).
Aber was kostet das "Zusammenschweißen"?
Wie viele Schritte braucht man, um 2 sortierte Reihungen der Länge 4
zu einer sortierten Reihung der Länge 8 "zusammenzuschweißen"?
(8 Schritte, weil man jede der 8 Komponenten einmal kopieren muss).
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 47
Merge-Sort:
Länge
n Komponenten
n
n/2
n/4
.
.
.
1
log2(n) Ebenen
●
●
●
●●●
1. Um eine Reihung der Länge n zu sortieren, teilen wir sie in zwei Hälften, und diese Hälften wieder in
zwei Hälften, und diese ... bis wir lauter Reihungen der Länge 1 haben.
2. Jede Reihung der Länge 1 ist bereits sortiert.
3. Dann führen wir zusammen (oder: dann mergen wir):
jeweils zwei (sortierte) Reihungen der Länge 1 zu einer sortieren Reihung der Länge 2
jeweils zwei sortierte Reihungen der Länge 2 zu einer sortierten Reihung der Länge 4
jeweils zwei sortierte Reihungen der Länge 4 zu einer sortierten Reihung der Länge 8
...
zwei sortierte Reihungen der Länge n/2 zu einer sortierten Reihung der Länge n.
Mergesort hat immer (in einem besten, in einem durchschnittlichen und in einem schlechtesten Fall)
eine Zeitkomplexität von O(n * log(n)).
Eine gute Darstellung von mergesort im Netz: http://de.wikipedia.org/wiki/Mergesort
Die Sortier-Algorithmen bubblesort, selectionsort und insertionsort haben eine Zeitkomplexität O(n2).
Mergesort hat eine Zeitkomplexität O(n * log(n)).
Aufgabe: Um welchen Faktor ist n* log(n) kleiner als n2, wenn n gleich 1 Million ist?
Lösung: Etwa um den Faktor 1 Million / 20 (gleich 50 Tausend).
Eine negative Eigenschaft von mergesort: Um z.B. eine 1 MB große Reihung zu sortieren braucht man
2 MB Speicher (die zu sortierende Reihung und noch mal soviel).
Eine positive Eigenschaft: mergesort ist stabil, d.h.
die Reihenfolge von Komponenten mit gleichen Schlüsseln wird nicht verändert.
Beispiel: Wir sortieren Adress-Objekte zuerst nach Vornamen, und danach nochmal nach Nachnamen.
Danach sind sind dann alle Adressen mit gleichen Nachnamen (z.B. "Schmitz") nach Vornamen sortiert
(z.B Schmitz, Alfred / Schmitz, Berta / Schmitz, Carl etc.). Bei einem einem nicht-stabilen Sortierverfahren wäre das nicht garantiert.
Wenn Zeit dazu ist: Öffnen Sie die Datei MergeSort01.java und ersetzen Sie die mit
// MUSS ERSETZT WERDEN
gekennzeichneten Zeilen durch geeignet Java-Befehle. Empfehlung: Schreiben Sie die Befehle erst mal
mit Papier und Bleistift (es sind nicht sehr viele Zeilen).
S. 48, SS15
SU 17. Do 25.06.15, Block 3
Beuth-Hochschule
Zur Entspannung: Die Kreiszahl Pi mit Hilfe von Zufallszahlen berechnen
Datei PiMitZufallszahlen.pdf öffnen.
Die Klasse Random und die Objektmethode Random::nextDouble.
Das Intervall [0.0 .. 1.0) (einschließlich 0.0, ausschließlich 1.0).
Schon im 15. Jahrhundert hat der Perser Dschamschid Mas'ud al-Kaschi Pi auf 16 Stellen genau berechnet. 1873 veröffentlichte William Shanks 707 (von Hand berechnete) Stellen von Pi, aber leider waren
nur die ersten 527 korrekt. 2013 wurde Pi von Shigeru Kondo und Alexander Yee (und einem Computer)
auf auf mehr als 12 Billionen Dezimalstellen genau berechnet.
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 49
SU 18. Do 02.07.15, Block 1
Test 6
Graphen
Das Papier Dijkstra.pdf (9 Seiten) besprechen.
Def.: Ein Graph besteht aus Knoten und Kanten.
Jede Kante verbindet zwei (nicht notwendig verschiedene) Knoten.
Es gibt viele Arten von Graphen, die sich durch folgende Eigenschaften unterscheiden:
Gerichtet/ungerichtet, Ohne/Mit Schleifen, Ohne/Mit Mehrfachkanten, Einfache G.,
Kanten-gewichtete G., Knoten-geweichtete G., Zusammenhängende/unzusammenhängende G.
Aufgabe-01 und -02 bearbeiten (in 2-er-Gruppen)
Lösung-01: N-1, Lösung-02: N * (N-1) / 2 (Achtung: Nicht dem Gauß-Trick verwechseln!)
Implementierungen von Graphen
Verschiedene Algorithmen, die Graphen bearbeiten, stellen unterschiedliche Anforderungen: Einige wollen direkt auf jeden Knoten zugreifen können (random access), anderen genügt es, sequentiell auf die
einzelnen Kanten zuzugreifen etc. Deshalb gibt es verschiedene Implementierungen von Graphen.
Grundbegriffe: dichte Graphen, dünne Graphen, benachbarte (adjazente) Knoten, inzidente Knoten und
Kanten.
Drei verschiedene Implementierungen von Graphen
Für einen ungerichteten Graphen mit N Knoten, M Kanten und S Schleifen gilt:
Bezeichnung der Implementierung
Kurze Beschreibung
Nachbarschafts-Matrix (Adjazenz-Matrix)
Eine "halbe" NxN-Matrix von boolean-Werten
Inzidenz-Matrix
Eine NxM-Matrix von boolean-Werten
Nachbarschafts-Listen (Adjazenz-Listen)
Für jeden Knoten eine Liste seiner Nachbar-Knoten
(insgesamt N + 2*M - S Komponenten)
Frage: Wie berechnet man die Anzahl der Komponenten einer "halben" NxN-Matrix?
Antwort: Mit dem Gauß-Trick: (N+1) * N/2
Aufgabe-03 und -04 (auf S. 3) in 2-er-Gruppen bearbeiten.
Lösung-03: 5_050, 20_000,
500
Lösung-04: 5_050, 400_000, 8_100
Die Nachbarschafts-Listen sind vom Speicherbedarf her sowohl für dichte als auch für dünne Graphen
geeigneten, erlauben aber keinen Direktzugriff (nur sequentiellen Zugriff) auf die einzelnen Kanten. Eine
Nachbarschafts-Matrix ist gut für dichte Graphen, nicht so gut für dünne Graphen.
Zur Entspannung: Ist der folgende Satz wahr oder nicht?
Dieser Satz enthält trei Fähler!. Stimmt das oder nicht? Offenbar enthält der Satz zwei syntaktische
Fehler (trei statt drei und Fähler statt Fehler) und einen semantischen Fehler (drei statt zwei). Damit ist
er also wahr. Aber wenn er wahr ist, enthält er keinen semantischen Fehler und ist somit falsch. Aber
wenn er falsch ist, enthält er einen semantischen Fehler und ist somit wahr. Aber wenn er ... .
Ü1b-06, Do 02.07.15, Block 2
Siehe Seite 45 (GleitBitsFloatApplet und GleitBitsDoubleApplet ausprobieren)
S. 50, SS15
SU 19. Do 02.07.15, Block 3
Beuth-Hochschule
SU 19. Do 02.07.15, Block 3
Aufgabe-05, -06, -07 (einen gerichteten Graphen darstellen als Nachbarschafts-Matrix, als InzidenzMatrix und als Reihung von Nachbarschafts-Listen)
Lösung-05: Nachbarschafts-Matrix für GG1:
v1
v2
v3
v4
v1
f
t
f
t
v2
f
t
t
t
v3
f
f
f
t
v4
f
t
f
f
Lösung-06: Inzidenz-Matrix für GG1:
Entweder eine Matrix mit Komponenten, die 4 Werte haben können: a (wie Anfang), e (wie Ende), b
(wie beides, für Schleifen) und leer (für nix):
e1
v1
a
v2
e
e2
e3
e4
e5
e6
e7
a
e
e
a
a
b
a
e
v3
a
e
v4
e
Oder zwei boolean-Matrizen, eine für Kanten-Anfänge und eine für Kanten-Enden
(alle nicht mit t gekennzeichneten Komponenten enthalten f):
ANF
e1
v1
t
e2
e4
e5
e6
t
t
t
v3
t
v4
END
e7
t
t
v2
e3
e1
e2
t
t
e3
e4
e5
e6
e7
v1
v2
t
t
v3
t
v4
Lösung-07: Nachbarschafts-Listen für GG1:
Knoten Liste von Nachbarn
v1
[v2, v4]
v2
[v2, v3, v4]
v3
[v4]
v4
[v2]
t
t
Beuth Hochschule
Stichworte zu Algorithmen
SS15, S. 51
Der Algorithmus von (Edsger Wybe) Dijkstra (1930 - 2002) (S. 4)
Probleme welcher Art löst dieser Algorithmus? "Was kann man damit machen?".
Achtung: Auf einigen Netzseiten wird dieser Algorithmus beschrieben, ohne dass exakt erklärt wird,
welche Probleme er löst.
Beispiel-01 (S. 4 bis 6) besprechen.
Aufgabe-08 bearbeiten (in 2-er-Gruppen)
Aufgabe-09 bearbeiten (in 2-er-Gruppen)
Aufgabe-10 bearbeiten (in 2-er-Gruppen)
Zur Entspannung: Kurt Gödel (1906-1978, Österreich-Ungarn, Princeton, USA)
Studierte Physik und Mathe in Wien, frühe Begabung für Mathe.
1931: "Über formal unentscheidbare Sätze der Principia Mathematica und verwandte Sätze". Die Principia Mathematika (3 Bände, erschienen 1910-1913) war ein philosophisch-mathematisch wichtiges Werk
von Bertrand Russell (1872-1970) und Alfred North Whitehead (1861-1947).
Mit diesem Papier zerstörte Gödel die Hoffnung des Mathematikers David Hilbert (1862-1943), alle
mathematischen Sätze rein formal aus einer Basis von Axiomen abzuleiten.
1932: Habilitation in Wien.
1933: Hitler kam an die Macht.
1934: Vorlesungen in Princeton.
1938: "Anschluss" Österreichs an Deutschland.
1940: Auswanderung in die USA, bis 1978 in Princeton, Freund von Einstein. "Consistency of the Axiom of Choice and the Generalized Continuum Hypothesis with the Axioms of Set Theory".
Einer der bedeutendsten Mathematiker des 20. Jahrhunderts. Starb in einer Nervenheilanstalt an Unterernährung, weil er Angst vor einer Vergiftung hatte.