Inhalt: - ITET.ch.vu

Werbung
Infomratik II
Inhalt:
Korrektheitsnachweis (Invarianten und vollst. Indukt.)
Robustes Programmieren mit Ausnahmen (exceptions)
Java: C-Level
Java-Klassen als Datenstrukturen
Dynamische Klassen und Referenzen
Bäume
Syntaxdiagramme
Rekursiver Abstieg
Infix, Postfix, Operatorbaum, Stack
Codegenerierung, Compiler, Interpreter
Java-VM als Bytecode-Interpreter
Pakete
Klassenhierarchie
Polymorphie
Abstrakte Klassen
Suchbäume, Sortieren
Backtracking
Spieltheorie, Minimax, AlphaBeta
Rekursives Problemlösen (Hanoi, Mergesort)
Effizienz, O-Notation
Simulation (zeitgesteuert, ereignisgesteuert)
Heap, Heapsort
Pseudoparallelität
Threads in Java
Algorithmus in Java:
- ägyptisches Multiplikations-Verfahren: a*b: a verdoppeln, b halbieren bis eins; alle a
wo b gerade streichen; restliche a aufsummieren. Beweis: Induktion nach b
- Exceptions:
try {
…
} catch (Fehlertyp e) {
…
}
Java:
- Programmstruktur: - import … importiert Pakete aus anderen Klassen, - Methode:
Funktionen oder Prozeduren anderer Sprachen, - Konstruktor: Methode die beim
erzeugen der Klasse automatisch aufgerufen wird, - main-Methode: public static void
main (String[] args) { … }
- static int i im Klassenkörper sind globale Variablen
- Integer: byte (8 bit), short (16 bit), int (32 bit), long (64 bit)
Gleitkommazahl: float (32 bit), double (64 bit)
Zeichen (Unicode): char (16 bit): Literale ‘a’, ‘/’, ‘3’
boolean Literale: true, false
String msg = „Hallo“ oder msg = new String(„Hallo“); + zum Veketten;
s1.compareTo(s2) Vergleich
- Arrays: int [] x; x = new int[7] (Index 0…6!!!) x[0] = 3, x.length gibt Länge;
mehrdimensional: float [] [] Matrix = new float [4] [4]
- Typenumwandlun: float myFloat = 3.12; int myInt = (int)myFloat; int i =
Integer.parseInt(s) von String zu Integer
- Hüllenklassen: int x = 5; Integer Huelle = new Integer(x);
System.out.println(Huelle.intValue());
- In-/Output: System.in.read() liest einzelnes Zeichen ein (char).
System.out.println(„bla“) Output. DataInputStream eingabe = new
DataInputStream(System.in); String zeile = ein.readLine(); int Zahl =
Integer.parseInt(zeile); (import java.io.* und Exception-Handling nicht vergessen)
Java Klassen als Datenstrukturen:
- Beispiel: class Datum { private int Tag, Monat, Jahr; (interne Variabeln im
Klassenkopf definiert) public Datum(int T, int M, int J) {Tag = T; Monat = M; Jahr =
J;} (Konstruktor) public void Ausgeben() { System.out.prinln(Tag +
„.“+Monat+“.“+Jahr);} (eine Methode) }
- Klassenmethoden werden als static deklariert. (Im Gegensatz zu Instanzenmethoden.)
Dynamische Klasen und Referenzen:
- Datum Heute = new Datum(…); Heute ist eine Referenzvaribale, mit new wird die
dynamische Variable erzeugt
- Klasse kann auch „Variablen vom eigenen Typ“ im Konstruktor haben. (Anwendung
Listen etc.)
- Wenn Heute=Morgen; gemacht wird, zeigen beide auf das selbe Objekt, die
dynamische Variable von Morgen geht verloren!!!
Syntaxanalyse und Übersetzung:
- Bäume: Kanten und Knoten (#Knoten = 1 + #Kanten), je Knoten eine Kante, keine
Zyklen o.ä. Blatt = Knoten am Ende des Baumes
Darstellungen: Graph (ev. gerichteter), Mengendiagramm, eingerückte Form,
-
-
-
-
Linksklammerdarstellung. (Siehe S. 66)
Binärbäume Æ Arraydarstellung
Syntaxdiagramme: „Nicht-Terminalsymbole“ (eckig, = rekursiver Aufruf eines
anderen Syntaxdiagramms oder sich selbst) und „Terminalsymbole“ (rund, = Zeichen)
Anwendung: Parser, der einen Ausdruck auf Korrektheit überprüft.
Symmetrisches traversieren eines Binärbaumes (inorder): 1. linker Unterbaum, 2. sich
selbst (Konten), 3. rechter Unterbaum. (Z.b. für Operatorbäume mit *, +, etc.)
Postfix: Zuerst die (beiden) Ausdrücke, dann der Operator. (Infix: a+b, Postvix: ab+)
Æ postorder traversieren des Binärbaumes : 1. linker Unterbaum, 2. rechter
Unterbaum, 3. sich selbst (Knoten)
Stack: (S. 82) mittels Array, push (Element drauflegen) und pop (oberstes Element
wegnehmen)
Postfixumwandlung mittels Stack: Operanden ausgeben, Operatoren in Stack,
schliessende Klammer Æ pop
Postfixauswerter: Operanden in Stack, Operatoren auf oberste beide Stackelemtene
anwenden und Resultat in Stack Æ am Schluss bleibt Resultat im Stack
Java-Bytecode: iconst_n (bipush n, wenn gleich für Operation verwendet wird???) (n
ein Integer), iconst_m1 (-1), istore_1, iload_1, iadd, imul, ireturn, if_icmpgt 28, goto
29, iand, ior, nop (do nothing) etc.
Z.b. a=1+2: iconst_1 iconst_2 iadd istore_0 (a zeigt nun auf die Adresse 0, in
welcher der Wert 3 steht.)
Pakete in Java:
- Paket = zusammengehörige Menge von Klassen. Paket b in Paket a: Paket a.b,
Deklaration: package test;
- Importieren von Klassen: import java.util.Random oder import java.util.* Æ kann nun
mit Random verwendet werden.
- Nur eine public class pro Datei Æ in mehrer Dateien aufteilen und in einem Package
zusammenfassen
- Eigene Pakete, z.B. für Listen: ListPackage.List
Objektorientierung:
- Vererbung (inheritance): Verallgemeinerung <-> Spezialisierung (Z.b. Rennfahrer ist
allgemein Sportler ist allgemein Mensch oder Mensch kann speziell Sportler sein…)
- Konzeptbaum (S. 111) der Klassenhierarachie. (class Fahrzeug {…} class Auto
extends Fahrzeug {…} class PW extends Auto {…} … Fahrzeug f; Auto a; erlaubt:
f=a; verboten: a=f;)
Überprüfung: if (f instanceof Auto) …
- Polymorphismus: Objekt kann verschiedene Formen annehmen. abstract class
geo_obj{ geo_obj next; public abstract double flaechenwert();} Abstrakte Methoden
müssen in abstrakten Klassen sein, abstrakte Methode wird je nach Objekt verschieden
definitert (PI * r2 für Kreis, a*b für Rechteck, …)
- Mehrfachvererbung (von verschiedenen übergeordneten Klassen) in Java nicht
möglich.
- Inteface deklariert Methoden, implementiert sie aber nicht. interface interf { boolean
kleiner(); boolean equal()} Muss von anderer Klasse implementiert werden: class S
implements iterf {public boolean kleiner() {…} …}
- Interface kann mehrere andere Intefaces erweitern: interface I extends J, K {…},
Klassen können nur eine Klasse erweitern, aber mehrere Interfaces implementieren:
class S extends P implements J, K
Exceptions:
- Ausgelöst vom System oder explizit im Programm (throw), können abgefangen
werden (catch).
- try {bla1; bla2;} catch (bla1Exception) {…} catch (bla2Exception) {…}
- Typische: IOException, Netz (z.B. MalformedURLException), Objekte erzeugen mit
new, Typenkonvertierung (z.B. NumberFormatException)
- Abfangen mit try – catch in der Methode oder mit public methode1() throws
java.io.IOException {…} wird der Fehler an die aufrufende Methode weitergereicht.
(Achtung: import java.io.* nicht vergessen)
- Beispiel: try{ out = new FileOutputStream(args[0]);} catch (Throwable e) {
System.out.println(“Error!”); System.exit(1);}
throwable ist oberste Fehlerklasse und fängt alles ab.
Zeigergeflechte:
- zyklische Liste (z.B. für das Josephus-Problem)
- Binärbäume als „Liste“, bei welcher jedes Element auf zwei weitere zeigt (left und
right) und ev. auch auf das Vorgänger-Element
- Binäre Suchbäume (left kleiner, right görsser):
Einfügen in Baum = durchlaufen bis zu bei Blatt angelangt (Æ links oder rechts
anfügen)
Löschen im Suchbaum: Bei Blättern und Knoten mit nur 1 Nachfolger einfach. Bei
Knoten mit 2 Nachfolgern: Ersetzen durch grösstes Element im linken oder durch
kleinstes Element im rechten Teilbaum
Inorder-Traversierung Æ Ausgabe ist aufsteigend sortiert.
- Sortieren mit Suchbäumen (mit n Knoten): Blatt nach ca. log(n) Schritten, InorderTraversierung braucht c*n Schritte Æ Zu sortierende Liste in Suchbaum überführen
und dann Inorder-Traversieren: c*n*log(n)
Binärsuche:
- Suche in Sortiertem Array: Liegt wert links oder rechts der Mitte? Æ Iterativ oder
Rekursiv auf entsprechende Hälfte anwenden.
Achtung: Abbruchbedingung: while(re >=li)…(nicht !=) sonst könnte es eine
Endlosschlaufe geben.
- Optimierung: Nicht einfach in der Mitte zu Suchen beginnen, sondern Abhängig von
der Grösse der gesuchten Zahl im Vergleich zur grössten Zahl (bzw. im Vergleich zur
Länge des Arrays.)
Backtracking:
- Systematisches Durchlaufen aller Möglichkeiten. (Baum)
- Beispiel: Das Spiel mit den 9 Quadraten, die nur auf eine Art zusammenpassen oder
das Schachbrett mit 8 Damen, die sich nicht bedrohen sollen.
- Backtracking: Im Baum ersten Ast ganz links nehmen. Dann das Teilproblem für den
Unterbaum lösen (unter den neuen Bedingungen).
- Strategie: Sackgassen möglichst früh entdecken Æ spart viel Aufwand (ganze
Unterbäume)
Spielbäume:
- Grundannahme: Jeder Spieler verhält sich rational und versucht möglichst grossen
Gewinn erreichen.
- Spiele endlich, rein strategisch, nur 2 Personen. (Koalitionen etc. bei n Spieler)
Nullsummenspiel, vollständige Information.
-
-
MiniMax-Algorhythmus (Negamax)
Bei binärem gewinn: sobald man eine sichere 1 hat, können die restlichen Äste
geschnitten werden.
Suchstrategien: depht-first, breadth-first, best first
Alpha-Beta-Algorithmus (Skript S. 180)
Nullfenster
… (!)
Rekursives Problemlösen:
- divide et impera
- z.B. Türme von Hanoi: Nur eine mögliche Situation am Ende Æ Teilproblemlösen
„rückwärts“
- Mergesort: unsortierte Liste wird mit „divide et impera“ zerlegt. Danach werden die
Listen wider zusammengeführt und immer gleich sortiert.
Komplexität von Algorithmen:
- O(f(n)), es wird vereinfacht: c*nÆn, c+nÆn, n+n2Æn2 (n eingabemenge)
- Beispiele: ägyptische Multiplikation (m,n) O(log(n)); hanoi O(2n); insertion/ deletion
sort O(n2); Sortieren mit Suchbäumen O(n*log(n)) (avarage) bis O(n2) (worst);
Mergesort O(n*log(n)); Binärsuche O(log(n))
- wir verwenden Ω ( f ( n ) ) (wächst mindestens so schnell, O: höchstens)
-
Übungen!!!!
Simulation:
- Simulation: Experimente an einem Simulationsmodell. (für komplexe Probleme). Im
Allgemeinen aufwendig.
- Modell: vereinfachtes Abbild der komplexen Realität
- Anwendungen: Optimierung, Entscheidungshilfe, Prognose, Validierung, Animation,
etc.
- Zeitgesteuerte (synchrone) Simulation: Pro Simulationsschritt Erhöhung um festes t
(gute Wahl!) Bsp: Katzen, Mäuse, Weizen
- spezielles: Schritte berechnen, Bedingungen für spezielle Situationen (Menge = 0 oder
= sehr gross); z.T. Random verwenden! Ausgabe ev. periodisch.
- Ereignisgesteuerte Simulation: Zustand bleibt zwischen zwei Ereignissen konstant,
Zeit springt von Ereignis zu Ereignis. Wichtig: Menge vorgemerkter Ereignis darf nie
leer werden Æ bearbeiten eines Ereignisses erzeugt immer mindestens ein neues
Ereignis in der Menge. z.B. Callcenter
- guter Trick: eintreffendes Ereignis (eingehender Anruf) würfelt Zeitpunkt des
nächsten selben Ereignisses aus (nächster Anruf) Æ es müssen nicht alle Ereignisse
von Anfang an eingeplant werden.
- Programmierung: z.B. Abstrakte Datentypen für Ereignisse, sortiert (priority queues).
insert und get_min nötige Funktionen.
- Heap-Datenstruktur: Binärbaum mit alle Niveaus gefüllt (von links nach rechts) und
Unterbäume enthalten immer grösseren Wert als ihre Wurzel.
get_min: 1. Wurzel entfernen, 2. letzen Knoten (unten rechts) nach oben nehmen. 3.
diesen so weit wie möglich nach unten wandern lassen (mit kleinerem Nachfolger
vertauschen)
insert: 1. ganz unten links anfügen, 2. nach oben wandern lassen, solange Vorgänger
grösser ist.
O(log(n)) Schritte
Heap als Array: Wurzel hat Index 1 (0 bleibt leer), Nachfolger von i sind 2i und 2i+1
-
Sortieren mit Heap: O(n*log(n)) und kein zusätzlicher Speicherbedarf!
Parallele Prozesse und Threads
- Prozess = Instanz eines laufenden Programms
- Zustand: laufend oder blockiert (siehe S. 263)
- PCB: Prozesskontrollblock
- Threads („Leichtgewichtsprozesse“): Kontextwechsel viel effizienter als bei Prozessen
- Java-Befehle für Threads: S. 268
- class myThread extends Thread { int mynumber; public myThread (int number)
{mynumber = number;} public void run() { … } }
- Erzeugen aus anderem Thread: myThread m = new myThread(5); m.start();
- alternative: new myThread(5).start(); kann aber nicht mehr kontrolliert werden.
- …………(S. 269)
Listen-Klasse und Operationen!!
(siehe Skript und Übungen)
Herunterladen