Folienmaster ETH Zürich

Werbung
Informatik II PVK
Tag 2
Michael Baumann
[email protected]
n.ethz.ch/~mbauman
|
|
Themen Theorie
1) Java Basics
2) Theorie: Komplexität und Laufzeit
3) OOP
|
|
2
Themen Praxis
1) Syntaxbäume
2) Verkettete Listen
3) Stacks
4) Binärsuche
5) Suchbäume
6) Spielbäume
7) Backtracking
8) Rekursion & Divide et impera
9) Simulation
10)Heaps
11)Parallelisierung
|
|
3
Binärsuche
|
|
4
Binary Search Fundamentals
●
●
Daten
●
Tupel aus Key und Nutzdaten
●
Sortiert nach Key
Finde einen gewissen Key
●
Möglichkeit 1: Alle durchgehen: O(n)
●
Möglichkeit2: BinarySearch
●
O(log n)
●
Annahme: Daten ungefähr gleichverteilt
|
|
5
Idee Binärsuche
●
Finde das Element mit Key 22
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3 4 9 15 17 22 23 24 27 28 32 34 37 38 40 41
27
●
begin: 0
●
end: 16
●
Middle: 16/2 = 8
22 < 27
|
|
6
Idee Binärsuche
●
Finde das Element mit Key 22
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3 4 9 15 17 22 23 24 27 28 32 34 37 38 40 41
27
●
begin: 0
●
end: 8
●
middle: 8/2 = 4
17
22 > 17
|
|
7
Idee Binärsuche
●
Finde das Element mit Key 22
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3 4 9 15 17 22 23 24 27 28 32 34 37 38 40 41
27
●
begin: 5
●
end: 8
●
middle: 13/2 = 6
17
23
22 < 23
|
|
8
Idee Binärsuche
●
Finde das Element mit Key 22
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3 4 9 15 17 22 23 24 27 28 32 34 37 38 40 41
27
●
begin: 5
●
end: 6
●
middle: 13/2 = 5
17
23
22
22 < 23
|
|
9
Pseudocode Binärsuche
Value b_search(List haystack, Key needle, int begin, int end) {
if(begin == end) return null;
middle = (begin + end)/2;
if(needle == haystack[middle].key) {
return haystack[middle].value
}
else if(needle < haystack[middle].key) {
return b_search(haystack, needle, begin, middle);
} else {
return b_search(haystack, needle, middle+1, end);
}
Verhindert Endlosschleife,
}
Falls das Element nicht existiert
|
| 10
Heuristik der Verteilung
●
Wir haben stillschweigend das arithmetische Mittel gewählt
middle = (begin + end)/2;
●
●
●
Das muss nicht sein, allgemein kann man hier durch
'factor' teilen
Idee: Mehr kleine IDs als grosse → Teile durch grössere
Zahl, so dass man schneller 'nach links' kommt
i.A. Annahme: Daten gleichverteilt → factor = 2 ideal.
|
| 11
Prüfungsrelevanz
●
Von Hand per Binärsuche etwas finden
●
In Java aufschreiben
●
●
Die Schnittstelle von haystack muss gegeben sein
●
Auf Grenzen achten!
Bedeutung des Paramters 'factor'
|
| 12
Suchbäume
|
| 13
Intermezzo: Binärbäume im Array
●
Jeder Knoten hat (max.) 2 Nachfolger
●
Die k-te Ebene braucht also Platz für 2^(k-1) Elemente
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5
●
Damit können wir den Baum super linear speichern
●
Kind1: (index * 2) + 1
●
Kind2: (index * 2) + 2
●
Vater: (index – 1) / 2
|
| 14
Binary Search Trees Fundamentals
●
●
●
Natürliche Erweiterung der Binärsuche
Idee: Lege die Pfade der Binärsuche nach allen möglichen
Elementen übereinander
Resultat:
●
Binärbaum
●
Alle Elemente im linken Teilbaum sind kleiner
●
Alle im rechten sind grösser
|
| 15
Suchbaum vs. Heap
|
| 16
Beispiel Suchbaum
50
10
80
35
51
92
24
|
| 17
Operationen im Suchbaum
●
isLeaf, hasOneChild
●
height
●
insert
●
find
●
remove
●
pre-, in-, postOrder
|
| 18
insert
public BinarySearchTree<T> insert(BinarySearchTree<T> tree, int key, T thing) {
if (tree == null) {
return new BinarySearchTree<T>(key, thing);
}
if (tree.key == key) {
tree.thing = thing;
} else if (key < tree.key) {
tree.left = insert(tree.left, key, thing);
} else {
tree.right = insert(tree.right, key, thing);
}
return tree;
}
|
| 19
insert Beispiel: Füge '68' ein
50
10
80
68
35
51
92
24
|
| 20
insert Beispiel: Füge '68' ein
50
10
80
68
35
24
51
92
68
|
| 21
remove: Drei Fälle
●
Blatt
●
●
1 Kind
●
●
Trivial, entferne es einfach
Entfernen und Kind an diese Stelle setzen
2 Kinder
●
●
Schwieriger
Setze das nächstgrössere (kleinstes im rechten
Teilbaum) an diese Stelle und entferne das bisherige
|
| 22
remove: 2 Kinder
public BinarySearchTree<T> remove(BinarySearchTree<T> tree, int key) {
...
UnlinkSmallestResult<T> result =
unlinkSmallest(tree.right);
result.smallest.right = result.tree;
result.smallest.left = tree.left;
return result.smallest;
...
}
|
| 23
remove: Hilfsfunktion unlinkSmallest
public UnlinkSmallestResult<T> unlinkSmallest(BinarySearchTree<T> tree) {
if (tree.left == null) {
return new UnlinkSmallestResult<T>(tree,
tree.right);
}
}
Nichts mehr links
-> Wir haben das Kleinste gefunden
|
| 24
remove: Hilfsfunktion unlinkSmallest
public UnlinkSmallestResult<T> unlinkSmallest(BinarySearchTree<T> tree) {
if (tree.left == null) {
return new UnlinkSmallestResult<T>(tree,
tree.right);
}
UnlinkSmallestResult<T> result =
unlinkSmallest(tree.left);
tree.left = result.tree;
return new UnlinkSmallestResult<T>(result.smallest,
tree);
}
Aktualisiere den linken Ast
und gib den neuen Teilbaum zurück
|
| 25
Aufgabe 2 Beispiel: Entferne '24'
50
10
80
35
24
51
92
68
|
| 26
Aufgabe 2 Beispiel: Entferne '24'
50
10
80
35
Blatt → Trivial!
51
92
68
|
| 27
Aufgabe 2 Beispiel: Entferne '10'
50
10
80
35
51
92
68
|
| 28
Aufgabe 2 Beispiel: Entferne '10'
50
35
80
51
Ein Kind → Einfach!
92
68
|
| 29
Aufgabe 2 Beispiel: Entferne '50'
50
35
80
51
92
68
|
| 30
Aufgabe 2 Beispiel: Entferne '50'
●
50
Finde kleinstes Element im
rechten Teilbaum
●
51
35
80
51
92
68
|
| 31
Aufgabe 2 Beispiel: Entferne '50'
●
●
●
50
Finde kleinstes Element im
rechten Teilbaum
51
35
Entferne dieses
●
51
Das ist einfacher
●
Warum?
80
51
92
68
|
| 32
Aufgabe 2 Beispiel: Entferne '50'
●
●
●
51
Finde kleinstes Element im
rechten Teilbaum
51
Entferne dieses
●
Das ist einfacher
●
35
80
68
92
Warum?
|
| 33
Aufgabe 2 Beispiel: Entferne '50'
●
●
●
51
Entferne dieses
●
Das ist einfacher
●
●
51
Finde kleinstes Element im
rechten Teilbaum
35
80
68
92
Warum?
Füge es an Stelle des zu
entfernenden ein
|
| 34
Sortieren per Suchbaum
●
Beobachtung: Suchbaum inOrder ausgeben → sortiert
●
Idee: Sortieren per Suchbaum
●
●
Füge alle Elemente in Suchbaum ein
●
Gib in inOrder aus
Laufzeit:
●
Gut durchmischt: O(n*log n)
●
Vorsortiert: O(n2)
●
Degenerierter Baum: Liste
●
Deshalb in der Praxis selten verwendet
|
| 35
Prüfungsrelevanz
●
Darstellung Binärbaum in Array
●
Operationen auf Binärbaum
●
●
Löschen(!)
●
Zumindest von Hand
Sortieren per Suchbaum nicht so wichtig
|
| 36
Spielbäume
|
| 37
Spielbäume & Spieltheorie
●
Aufbau von Spielbäumen
●
●
Füge alle möglichen Züge als Kinder des aktuellen Zugs
ein
Strategie
●
Für JEDE Möglichkeit einen Zug wählen
●
Eine Kante von jedem Zustand „unseres“ Spielers
●
Also nicht nur ein Ast
●
Oder gar eine Kante
|
| 38
Eine Strategie
MAX
4
4
4
3
7
7
-5
MIN
-2
0
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 39
Keine Strategie
MAX
4
4
4
3
7
7
-5
MIN
-2
0
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 40
Gar keine Strategie
MAX
4
4
4
3
7
7
-5
MIN
-2
0
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 41
Minimax
●
Zwei Spieler (MIN und MAX) wechseln sich ab
●
MAX-Spieler wählt den besten Zug für sich
●
MIN-Spieler wählt den schlechtesten Zug für MAX
●
Algorithmus
●
MAX-Stufe: Wert = max{Werte der Kinder}
●
MIN-Stufe: Wert = min{Werte der Kinder}
|
| 42
Minimax
MAX
MIN
4
3
7
-5
MAX
-2
0
2
1
7
MIN
8
|
| 43
Minimax
MAX
MIN
4
3
7
7
-5
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 44
Minimax
MAX
4
4
3
7
7
-5
MIN
-2
0
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 45
Minimax
MAX
4
4
4
3
7
7
-5
MIN
-2
0
-2
2
0
2
1
MAX
8
7
MIN
8
|
| 46
Alpha-Beta
●
Manche Teilbäume müssen gar nicht analysiert werden
Max
Min könnte -1 erreichen
Max kann 0 erreichen
-> Max wird nicht diesen Zug
wählen
Min
Max
Min
|
| 47
Alpha-Beta: Algorithmus
●
Führe ein Intervall [α, β] mit
●
Min aktualisiert β (verkleinert es) und gibt β zurück
●
Max aktualisiert α (vergrössert es) und gibt α zurück
●
Schnitte:
●
Max: Neues α ≥ β → β-cut
●
Min: Neues β ≤ α → α-cut
●
Unser Beispiel: 2 α-cuts
|
| 48
Alpha-Beta: Üben
●
Beispiel auf PVK-Website
●
Beispiel sehr detailliert simuliert
http://vs.inf.ethz.ch/edu/i2/slides/Info2-ITET-AlphaBeta.pdf
●
Java Applet
http://www.ocf.berkeley.edu/~yosenl/extras/alphabeta/alphabeta.html
|
| 49
Prüfungsrelevantes
●
Einfacher Spielbaum aufbauen (Tic-Tac-Toe oder so)
●
Minimax ausfüllen
●
AlphaBeta
●
●
●
Richtige Cuts setzen
Intervalle und Unterscheidung α/β-Cut wahrscheinlich
nicht nötig
Möglicherweise Min / Max-Funktion ausfüllen (Lückentext)
|
| 50
Backtracking
|
| 51
Späckträcking
●
Verbessertes Brute Force
●
Grosser Suchraum, so dass Brute Force zu lange braucht
●
Probiere nicht alle Möglichkeiten durch
●
Brich so bald wie möglich ab...
●
...und gehe einen Schritt zurück.
|
| 52
Template Backtracking
boolean backtrack(data, depth) {
if(solved()) {
return true;
}
for(possible_move in data) {
make_move(possible_move);
if(backtrack(data, depth+1) == true) {
return true;
}
}
revert();
return false; //backtracking
}
|
| 53
Vergleich Brute Force ↔ Backtracking
●
●
Brute Force führt alle „Züge“ auf einmal aus
●
Merkt dann, dass es nicht geht...
●
...und versucht die nächste Kombination
Backtracking macht jeden Zug einzeln
●
Merkt, dass es nicht geht...
●
...und geht einen Zug zurück
|
| 54
Bsp. Sudoku: Brute Force
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 |
| 55
Bsp. Sudoku: Brute Force
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 2 |
| 56
Bsp. Sudoku: Brute Force
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 3 |
| 57
Bsp. Sudoku: Backtracking
1 2 4 8 9 ?
|
| 58
Bsp. Sudoku: Backtracking
1 2 6 4 9 8
...
|
| 59
Prüfungsrelevantes
●
Idee Backtracking
●
●
Schritt für Schritt, Abbruch sobald hoffnungslos
Backtracking ↔ Brute Force
|
| 60
Divide et impera
|
| 61
Divide et impera
●
Kennt ihr bestens
●
Problem ist schwierig
●
Führe es zurück auf ein kleineres Problem, das einfacher
zu lösen ist
●
●
IdR. rekursiv
Löse dieses und mache wenige Anpassungen
|
| 62
Beispiel Divide et impera: Mergesort
●
Sehr wichtig: Eines der häufigsten Sortierverfahren
●
InPlace möglich
●
Algorithmus
●
Liste leer / 1 Element → return (fertig)
●
Teile die Liste in zwei Teillisten
●
Sortiere diese
●
Füge die sortierten Listen in eine grosse zusammen
●
Nimm jeweils das kleinste von beiden
63
Mergesort
private ArrayList<T> mergesort(ArrayList<T> items, int begin, int end) {
if (begin == end) {
return new ArrayList<T>();
}
if (begin + 1 == end) {
ArrayList<T> result = new ArrayList<T>();
result.add(items.get(begin));
return result;
}
int middle = begin + (end­begin) / 2;
ArrayList<T> left = mergesort(items, begin, middle);
ArrayList<T> right = mergesort(items, middle, end);
return merge(left, right);
}
|
| 64
Mergesort
private ArrayList<T> merge(ArrayList<T> left, ArrayList<T> right) {
int leftIdx = 0;
int rightIdx = 0;
ArrayList<T> sorted = new ArrayList<T>();
while(true) {
if (leftIdx == left.size()) {
sorted.addAll(right.subList(rightIdx, right.size()));
return sorted;
}
if (rightIdx == right.size()) {
sorted.addAll(left.subList(leftIdx, left.size()));
return sorted;
}
if (left.get(leftIdx).compareTo(right.get(rightIdx)) < 0)
sorted.add(left.get(leftIdx++));
else
sorted.add(right.get(rightIdx++));
}
}
|
| 65
Prüfungsrelevantes
●
Idee Divide et impera
●
Mergesort
|
| 66
Simulation
|
| 67
Simulation
●
Komplexe Vorgänge per Computer nachspielen
●
Möglichst schnell genaues Ergebnis
●
Zwei Arten
●
Zeitgesteuert
●
Ereignisgesteuert
|
| 68
Zeitgesteuerte Simulation
●
Zustand zur Zeit tk bekannt
●
Berechne Änderungen tk→tk+1
●
Wiederhole, so lange tk > tmax
|
| 69
Probleme Zeitgesteuerte Simulation
●
Häufig passiert lange Zeit gar nichts...
●
...und dann viel auf einmal
●
●
Bei konstantem Zeitschritt verlieren wir in den „Totzeiten“
viel Rechenzeit
Möglichkeiten
●
Schrittweitensteuerung (i.A. schwierig)
●
Ereignisgesteuerte Simulation
|
| 70
Ereignisgesteuerte Simulation
●
Idee: Liste von Ereignissen mit Zeitpunkt
●
Bei Eintreffen von Ereignis werden neue berechnet
●
Eigenschaften
●
Keine verschwendete Rechenzeit
●
Kausalität nicht gegeben
●
●
Bei guter Modellierung nicht wichtig
Beispiel Telefonzentrale
|
| 71
Prüfungsrelevantes
●
Vor- & Nachteile Zeit- & Ereignisgesteuerte Simulation
●
Implementation einer einfachen zeitgesteuerten Simulation
|
| 72
Heaps
|
| 73
Heap Fundamentals
●
Einsatzzweck von Heaps: Priority-Queues
●
●
Ereignisgesteuerte Simulationen!
Struktur
●
Binärbaum
●
Alle Kinder sind kleiner (Max-Heap)...
●
...oder grösser (Min-Heap) als der Vater
●
Immer kompakt
●
Kann im Gegensatz zu Suchbaum nicht zur Liste
degenerieren
|
| 74
Suchbaum vs. Heap
|
| 75
Das ist ein Heap
1
4
7
9
8
51
29
24
|
| 76
Das ist kein Heap
1
4
7
9
8
51
29
24
|
| 77
Operationen im Heap
●
Insert: O(log n)
●
●
●
Füge das Element am Schluss des Heaps ein (Heap
vergrössern)
Propagiere es so weit wie möglich nach oben
(Vertauschen mit kleinerem Kind)
get_min / get_max: O(log n)
●
Entferne die Wurzel und gib es zurück
●
Setze das letzte Element auf die Wurzel
●
Propagiere es so weit wie möglich nach unten
|
| 78
Insert: Füge '2' ein
1
2
4
7
9
8
51
29
24
|
| 79
Insert: Füge '2' ein
1
4
7
24
9
8
51
29
2
|
| 80
Insert: Füge '2' ein
1
4
2
24
9
8
51
29
7
|
| 81
Insert: Füge '2' ein
1
2
4
24
9
8
51
29
7
|
| 82
get_min
1
2
4
24
9
8
51
29
7
|
| 83
get_min
7
2
4
9
8
51
29
24
|
| 84
get_min
2
7
4
9
8
51
29
24
|
| 85
get_min
2
4
7
9
8
51
29
24
|
| 86
Insert (Min-Heap)
private void insert(ArrayList<T> items, int index) {
int father = father_position(index);
if(items.get(index).compareTo(items.get(father)) < 0) {
swap(items, index, father);
insert(items, father);
}
}
|
| 87
get_min (Min-Heap)
private void sink(ArrayList<Integer> items, int i) {
if(leftchild(i) >= n) {
return;
}
int childindex = leftchild(i);
if(rightchild(i) < n){
if(items.get(leftchild(i)) < items.get(rightchild(i))
childindex = rightchild(i);
}
if(items.get(i) < items.get(childindex)){
swap(items, i, childindex);
sink(items, childindex, n);
} else {
return;
}
}
|
| 88
Heapsort
●
●
Idee ähnlich wie bei sortieren per Suchbaum
●
Füge alles einmal ein...
●
...und lese es wieder raus
Algorithmus: O(n*log n)
●
●
Füge alle Elemente in einen Max-Heap ein
Lies das grösste Element aus und füge es VORNE in die
sortierte Liste ein
●
Alternativ: Min-Heap und hinten einfügen
●
In Place-Implementierung: Siehe Serie 12
|
| 89
Prüfungsrelevantes
●
Definition Heap
●
Unterschiede Heap ↔ Suchbaum
●
Operationen implementieren können
●
●
insert
●
get_min
Heapsort
|
| 90
Parallelisierung
|
| 91
Gleichzeitigkeit, Prozess ↔ Thread
●
Gleichzeitigkeit auf zwei Arten erreichbar
●
●
●
Mehrere Prozessoren → „wirklich gleichzeitig“
Schnell zwischen allen Prozessen wechseln →
erscheinen gleichzeitig
Prozess ↔ Thread
●
Prozesswechsel sind teuer, deshalb Thread:
●
„Leichtgewichtsprozess“
●
Kein Adressraumwechsel etc.
●
Mehr Parallelität möglich
|
| 92
Scheduling
●
●
Ein Thread kann CPU freigeben (yield)...
...je nach dem macht das auch des Scheduler (preemptive
scheduling)
|
| 93
Threads in Java
●
java.lang.Thread
●
start
Starte in neuem Thread
●
sleep
●
run
Starte in diesem Thread
●
join
●
suspend
●
getPriority
●
stop
●
setPriority
●
resume
●
setDaemon
●
wait
●
yield
Warte, bis Thread fertig
|
| 94
Race conditions, Critical sections
●
Zwei Prozesse greifen auf die gleichen Daten zu
●
Reihenfolge der Zugriffe unbekannt
●
Unabhängig von der Reihenfolge muss der Zustand
konsistent sein.
●
Es dürfen keine Änderungen verloren gehen
●
Lösung: synchronized
|
| 95
synchronized
●
●
Ist ein Prozess in einem synchronized-Block, kann kein
weiterer in einen verwandten synchronized-Block kommen
Benötigen ein lock-Objekt
●
Muss für alle Threads das gleiche sein
static Object lock = new Object();
...
synchronized(lock) {
...
}
●
Aufpassen: Starvation durch Mutex!
|
| 96
Prüfungsrelevantes
●
Zustände Prozess, Thread
●
Übergangsoperationen
●
Race conditions, Critical sections
●
synchronized-Schlüsselwort
|
| 97
Herunterladen