Informatik II PVK Tag 1 Michael Baumann [email protected] n.ethz.ch/~mbauman | | Grundsätzliches ● Alle Materialien verfügbar unter n.ethz.ch/~mbauman ● Sinn des PVK ● Kurze Repetition der wichtigen Konzepte ● Lösen einiger kurzer Aufgaben ● Tipps zur Prüfung ● NICHT neues Hintergrundwissen / Zeug aus der Vorlesung vertiefen ● ● Ziel: Ihr besteht alle die Prüfung Informatik ist Übungssache | | 2 Themen Theorie 1) Java Basics 2) Theorie: Komplexität und Laufzeit 3) OOP | | 3 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 | | 4 Java Fundamentals | | 5 Java Basics ● Die (relevanten) Schlüsselwörter abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while Unused; Dem C++-const enspricht final | | 6 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); } static int f(int a, int b){ if (b == 1) return a; if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 7 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); Unser Programm befindet sich } im package static int f(int a, int b){ 'demos' if (b == 1) Entspricht in etwa dem C++ return a; 'namespace' if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 8 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); } public: static int f(int a, int b){ Die Klasse soll ausserhalb des if (b == 1) packages sichtbar sein return a; if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 9 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); } static int f(int a, int b){Eine Klasse if (b == 1) return a; if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 10 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); } Nach aussen sichtbare static int f(int a, int b){ Funktion if (b == 1) return a; if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 11 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); static: } Funktion existiert pro Klasse, static int f(int a, int b){ nicht pro Objekt if (b == 1) -> Klasse muss nicht instanziiert return a; werden if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 12 Ein Java-Programm package demos; public class Mult { public static void main(String[] args) { int i = 5, j = 9; System.out.println(i + " * " + j + " = " + f(i,j)); } static int f(int a, int b){ main übernimmt immer if (b == 1) dieses Argument return a; if (b % 2 == 0) return f(a + a, b / 2); else return a + f(a + a, b / 2); } } | | 13 Primitive Datentypen ● ● Werden in der Speicherverwaltung anders behandelt Effizienz: Byte-Darstellung ohne OOP-Overhead ● Wrapper-Klassen ● int: Integer, … | | 14 Java Speicherverwaltung ● Einfacher als C++ ● Aber undurchsichtiger ● Keine Pointer ● Dafür Referenzen ● Löschen (delete) übernimmt der GarbageCollector ● Funktionsaufrufe: „Call by value using reference“ ● Ausnahme bei allem: Primitive Typen | | 15 Beispiel Speicherverwaltung SomeType p1, p2; p1 = new SomeType(); p1.property = 42; p2 = p1; System.out.println(p1==p2); // ?!? p2 = new SomeType(); p2.property = 42; System.out.println(p1==p2); // ?!? p1 = null; | | 16 Beispiel Speicherverwaltung SomeType p1, p2; p1 = new SomeType(); p1.property = 42; p2 = p1; System.out.println(p1==p2); // true p2 = new SomeType(); p2.property = 42; System.out.println(p1==p2); // false p1 = null; | | 17 Parameterübergabe in Java ● Call-by-Value ● ● ● Daten werden kopiert Keine Verbindung zwischen Daten des Aufrufers und der Funktion Call-by-Reference ● ● Referenzen (Pointer) auf Daten werden übergeben Änderungen innerhalb der Funktion sind von aussen sichtbar | | 18 Parameterübergabe in Java ● ● Java benutzt immer Call-by-Value ● Bei primitiven Typen wird der Wert kopiert ● Bei Referenztypen wird die Referenz kopiert Wir können den Wert eines Parameters ändern, nicht aber den Ort, wo er hinzeigt | | 19 Parameterübergabe in Java public void move(Point p) { p.x1 += 1; p.y1 += 2; } Hauptprogramm ruft auf: move(myPoint) main(...) myPoint int x1; 5 int y1; 5 myPoint p int x1; 6 int y1; 7 Nach swap(...) myPoint int x1; 6 int y1; 7 p | | 20 Parameterübergabe in Java public void swap(Point p1, Point p1) { Point temp = p1; p1 = p2; p2 = temp; } Hauptprogramm ruft auf: swap(myPoint1, myPoint2) main(...) myPoint1 myPoint2 myPoint1 int x1; int y1; Nach swap(...) myPoint1 int x1; int y1; p1 p1 int x2; int y2; myPoint2 myPoint2 p2 int x2; int y2; int x1; int y1; int x2; int y2; p2 | | 21 Array ↔ ArrayList ● Array wie in C/C++ int x[] = new int[5]; for(int i = 0; i < 5; i++) x[i] = i; ● ArrayList<>: Entspricht C++ vector<> ● Wächst automatisch ● Java: Keine Operatorüberladung → keine [] ● set() auf falschen Index → IndexOutOfBoundsException ArrayList<Integer> x = new ArrayList<Integer>(); for(int i = 0; i < 5; i++) x.add(i, i); ● Indizes beginnen bei 0! | | 22 Bytecode ● C++ wird in (maschinenabhängigen) Assembler übersetzt ● Java wird in maschinenunabhängigen Bytecode übersetzt ● Dieser wird dann interpretiert ● Kompilieren und Bytecode ansehen ● Eclipse: .class-File reinziehen ● Terminal ● javac JavaTip.java //compiler ● java JavaTip //run ● javap –c –private JavaTip //disassembler | | 23 Bytecode Mnemonics ● ● ● Gute Liste: http://en.wikipedia.org/wiki/Java_bytecode_instruction_listi ngs Verkürzte Liste auf der PVK-Website Was müsst ihr können? ● (einfache) Bytecode-Programme interpretieren ● Nach Java zurückübersetzen ● NICHT selber Bytecode schreiben ● Sicher nicht die ganze Liste auswendig können (Wir sind keine Juristen) | | 24 Aufwand und Komplexität | | 25 Komplexität ↔ Aufwand ● Gegebene Problemgrösse (oft # Eingabeelemente) n ● Aufwand ● ● Wie schnell ist ein bestimmter Algorithmus: ● Günstigster Aufwand („best case“) ● Mittlerer Aufwand („average case“) ● Ungünstigster Aufwand („worst case“) Komplexität des Problems ● Eigenschaft des Problems, nicht des Algorithmus ● Aufwand des bestmöglichen Algorithmus | | 26 Asymptotische Laufzeit und O-Notation ● Bsp einer Laufzeit: 3*n2 + 5*n + 4*log(n) ● Die exakte Laufzeit ist nicht so interessant ● Für grosse n nur der n2-Term entscheidend ● ● Die '3' ist auch recht egal, ich kann ja einen schnelleren PC kaufen Deshalb: Asymptotische Laufzeit O(n2) ● ● „f wächst nicht wesentlich schneller als n2“ f ( n) Math. korrekt: lim 2 <∞ n→∞ n | | 27 Laufzeiten von Schleifen ● Schleifen nacheinander: Addition for(int i=0; i<2*n; i++) a++; for(int j=0; j<n; j++) a++; Addition: 2*n+n=3*n → O(n) ● Verschachtelte Schleifen: Multiplikation for(int i=0; i<n; i++) for(int j=0; j<n; j++) a++; Multiplikation: n*n=n² → O(n²) | | 28 Prüfungsrelevanz ● Komplexität eines Codes angeben ● ● Verschachtelte Schleifen Code auf gewünschte Laufzeit ergänzen | | 29 Objektorientierung | | 30 Visibility ● private ● ● protected ● ● Für Kindsklassen und Klassen des selben Pakets sichtbar public ● ● Nur innerhalb der Klasse sichtbar Für alle sichtbar Kapselung: Implementierung ist privat, Schnittstelle öffentlich | | 31 Vererbung ● Möglich: ● Ergänzen der Klasse (extends) ● Ändern von public / protected Funktionen ● Überschreiben von private-Funktionen ● Nicht möglich: ● Dinge entfernen ● Von mehreren Klassen erben ● Aber: Mehrere Interfaces implementieren ist möglich | | 32 Final ● Bisher: final (Java) ↔ const (C++) ● Neu: finale Methoden & Klassen ● Eine final-Methode kann nicht überschrieben werden ● Von einer final Klasse kann nicht vererbt werden ● z. B. Integer, Character, ... | | 33 Abstrakte Klassen ● ● Eine Klasse kann Methoden deklarieren, diese aber nicht implementieren Abgeleitete Klassen müssen diese implementieren ● ● Ausser sie sind selbst auch abstrakt Deklaration: public abstract class MyClass { public abstract void function(); } ● Object ist Basisklasse von allen anderen Klassen | | 34 Interfaces ● Implementieren keine Methoden ● Dienen zur Definition der Schnittstelle einer Klasse ● „Vertrag“ ● Methoden sind public abstract ● Eine Klasse kann mehrere Interfaces implementieren ● ● implements Ein Smartphone ist eine Implementation von Telefon und Computer | | 35 Beispiel Interface ↔ Abstrakte Klasse public interface IStack { int size(); void push(Object obj); Object pop(); Object peek(); boolean empty(); } public class MyStack implements IStack { private int size; public int size() { return size; } public void push(Object obj) { ... } ... } | | 36 Beispiel Interface ↔ Abstrakte Klasse public abstract class BaseStack implements IStack { public abstract int size(); public abstract void push(Object obj); public abstract Object pop(); public Object peek() { Object top = pop(); push(top); return top; } public boolean empty() { return size() == 0; } } public class MyStack extends BaseStack { private GenericList first; public Object peek() { return first.value; } ... } | | 37 Static und Dynamic Casting Casten ist „von unten nach oben“ möglich static cast ● Aa= b ● ● Muss zur Kompilierzeit überprüfbar sein, sonst Fehler dynamic cast ● A a = (A) b ● ● Darf zur Compilezeit unbestimmt sein Muss zur Laufzeit korrekt sein, sonst ClassCastException | | 38 Static und dynamic casts Person Student Employee Person p = new Person(...); Student s = new Student(...); Employee e = new Employee(...); Person ps = s Student sps = ps Person pe = e Student dsps = (Student) ps Student sp = p Employee deps = (Employee) ps | 21.06.15 | 39 Static und dynamic casts Person Student Employee Person p = new Person(...); Student s = new Student(...); Employee e = new Employee(...); Person ps = s ­> ok Person pe = e ­> ok Student sp = p ­> compile error Student sps = ps ­> compile error Student dsps = (Student) ps ­> ok Employee deps = (Employee) ps ­> runtime error | 21.06.15 | 40 instanceof Person Student Employee Person p = new Person(...); Student s = new Student(...); Employee e = new Employee(...); p instanceof Person true p instanceof Student false s instanceof Person true s instanceof Student true | 21.06.15 | 41 Generics ● ● ● Klasse auf beliebigen Typ implementieren Wiederverwertung von Code Generic-Typ kann wie eine normale Klasse verwendet werden public class MyClass<T extends BaseClass> { public abstract T function(); } | | 42 Das war der Theorieteil :) | | 43 Syntaxanalyse & -bäume | | 44 Grundlagen der Syntaxanalyse ● Beispiel arithmetische Ausdrücke 3*(6-2)+(4-2+5)*7 ● ● ● Lässt sich nur sehr mühsam Zeichen für Zeichen analysieren Die Multiplikation an Position 1 kann nicht sofort ausgeführt werden, da zuerst die Klammer ausgewertet werden muss. Idee: Rekursive Lösung | | 45 Bsp. arithmetische Ausdrücke (Skript S. 148 ff) ● Elemente ● Verzweigung: Beides möglich ● Kreis: bestimmtes Zeichen ● ● ● Rechteck: Aufruf an anderes Element Starte bei „Ausdruck“ Bei Misserfolg versuche einfach das nächst-mögliche | | 46 Bsp. arithmetische Ausdrücke (Skript S. 148 ff) void int_const() throws... { if(c < '0' || c > '9') { throw new InvalidIntException(); } readchar(); } void Ausdruck() throws... { Term(); while(c == '+') { readchar(); Term(); Es kann beliebig viele Terme } geben. Aber so lange noch ein } Plus kommt, muss auch ein Term kommen. | | 47 Bsp. arithmetische Ausdrücke (Skript S. 148 ff) void Term() throws... { Faktor(); while(c == '*') { readchar(); Faktor(); } } void Faktor() throws... { if(c == '(') { readchar(); Ausdruck(); if(c != ')') throw new BracketException(); } else int_const(); } | | 48 Pre-, In- und Post Order ● Pre Order: Gib zuerst das aktuelle Element aus, dann die Kinder ● ● In Order: Linkes Kind, aktuelles Element, rechtes Kind ● ● Infix: 3 + 4 Post Order: Aktuelles Element, dann beide Kinder ● ● „Polish“ / prefix: + 3 4 „Reverse polish“ / postfix: 3 4 + Folge der Stadtmauer | | 49 Prüfungsrelevanz ● Anhand von Diagrammen Gültigkeit entscheiden ● Im Normalfall Sachen, die nicht komplett offensichtlich sind, so dass nach Diagrammen gegangen werden muss. ● Code für eine Funktion einfügen ● Pre-, In- & Post-Order Ausgabe von Syntaxbäumen | | 50 Verkettete Listen | | 51 Idee der verketteten Liste ● Bisher kennen wir Arrays und ArrayList ● ● ● ArrayList hat den Vorteil, dass Java Vergrösserungen automatisch übernimmt. Man muss nicht mehr Platz allozieren Beide sind aber mühsam, wenn mehr Platz braucht: Alle alten Werte müssen kopiert werden. Idee der LinkedList: ● Die Werte müssen nicht in einem Block gespeichert sein ● Ein Element speichert zusätzlich den Ort des nächsten | | 52 Idee der verketteten Liste ● Ein Element ist ein Tupel aus ● Wert (beliebiger Datentyp) ● Referenz auf das nächste (C++: Pointer) myList value 76 value 15 value 22 value 3 value 32 next next next next next | | 53 Operationen auf verketteter Liste (Serie 5) ReadOnly Modifizierend ● add ● append ● size ● concat ● sum ● insertAt ● last ● remove ● sublist ● valueAt ● index | | 54 Rekursive Implementierung ● Idee ist immer gleich: ● ● ● Abbruchbedingung prüfen Falls nicht erreicht, „irgendwie“ an den Nachfolger übergeben Hier am Beispiel von index(List list, int value) public static int index(List list, int value) throws NoSuchElementException { if(list == null) throw new NoSuchElementException(); if(list.value == value) return 0; return 1 + index(list.next, value); } | | 55 Insertion Sort ● ● Sehr einfaches Sortierverfahren ● Gut geeignet für verkettete Listen ● O(n2) (recht schlecht) Idee ● Ein Element in eine sortierte Liste einfügen ist einfach ● Vor dem ersten grösseren einfügen (aufsteigend) ● Füge einfach alle Elemente in eine wachsende Liste ein ● Leere Liste ist sortiert | | 56 Insertion Sort ● InsertSorted public static List insertSorted(List list, int value) { if (list == null) return new List(value, null); if (value < list.value) return new List(value, list); list.next = insertSorted(list.next, value); return list; } ● sort public static List sort(List list) { if (list == null) return null; return insertSorted(sort(list.next), list.value); } | | 57 Prüfungsrelevanz ● Die rekursiven Operationen auf verketteten Listen kennen ● Funktionen ausfüllen können ● Mindestens in Pseudocode | | 58 Stacks | | 59 Grundlagen Stacks ● Stack = Stapel ● Menge Elemente in einer Liste ● ● Nur das oberste zugänglich ● LIFO (Last in first out) Schnittstelle unabhängig von Container ● Ihr habt (mind.) 2 implementiert: ● ArrayList ● LinkedList | | 60 Operationen Stack ● ● Minimale Schnittstelle: ● push: Neues Element auf Stack legen ● pop: Oberstes Element entfernen und zurückgeben ● peek: Oberstes Element anschauen aber drin lassen Weitere Operationen ● size ● empty ● toString | | 61 Prüfungsrelevanz ● Operationen kennen und implementieren können | | 62