Klausur zur Veranstaltung Programmierung (fortgeschrittene Konzepte) Bearbeitungszeit: 100 Minuten (14:15-15:55) Gesamtpunktzahl: 80 Punkte + 30 Zusatzpunkte Die Punktzahlen sind in etwa so bemessen, dass es pro Minute Bearbeitungszeit einen Punkt gibt. Zwar sind die Zusatzaufgaben die schwersten, aber wenn Sie Ihnen leichter erscheinen als reguläre Aufgaben, dann bearbeiten Sie lieber diese. Zum Bestehen sind 40 Punkte notwendig. Sollte der Platz auf dem Aufgabenblatt nicht ausreichen, dann verwenden Sie zusätzlich die Rückseite(n). Name, Vorname: Matrikelnummer: Veröffentlichung meines Ergebnisses: Veröffentlichung auf der Webseite der Veranstaltung unter den letzten beiden Ziffern meiner Matrikelnummer. Veröffentlichung auf der Webseite der Veranstaltung unter dem folgenden vierziffrigen Zahlencode: Keine Veröffentlichung meines Ergebnisses auf der Webseite der Veranstaltung.
Aufgabe 1 (15 Punkte) Das folgende Codesegment speichert geometrische Objekte unter einem Schlüssel vom Typ String in einer Hashtable. Anschließend werden einige geometrische Objekte mittels ihres Schlüssels aus der Hashtable ausgelesen und ihr Flächeninhalt ausgegeben. Hashtable mytable= new Hashtable(); mytable.put("rechteck1",new Rechteck(2.0,3.5)); mytable.put("kreis1",new Kreis(2.5)); mytable.put("kreis2",new Kreis(4.0)); GeomObjekt g1 = (GeomObjekt)myTable.get("Rechteck1"); System.out.println(g1.flaecheninhalt()); GeomObjekt g2 = (GeomObjekt)myTable.get("Kreis2"); System.out.println(g2.flaecheninhalt()); Wie Sie leicht erkennen können, stammt dieser Code aus einer Zeit, in der es noch keine Generics gab. Sie wollen allerdings auf die Vorteile von Generics nicht verzichten. Schreiben Sie deshalb den Code so um, dass er Generics verwendet. Eplizite Typecasts und instanceof-abfragen sollen in der Lösung nicht vorkommen. Hashtable<String,GeomObjekt> mytable= new Hashtable<String,GeomObjekt>(); mytable.put("rechteck1",new Rechteck(2.0,3.5)); mytable.put("kreis1",new Kreis(2.5)); mytable.put("kreis2",new Kreis(4.0)); GeomObjekt g1 = mytable.get("rechteck1"); System.out.println(g1.flaecheninhalt()); GeomObjekt g2 = mytable.get("kreis2"); System.out.println(g2.flaecheninhalt());
Aufgabe 2 (18 Punkte) Anton(A), Berta(B) und Charly(C) sind in einem Chatroom miteinander verbunden, in dem jeder alle Nachrichten von jedem lesen kann. Anton schreibt die Nachricht Wie gehts Euch?. Etwa zur gleichen Zeit, schreibt Charly, bevor er die Nachricht von Anton empfangen hat, die Nachricht Hallo allerseits!. Berta hat bereits die Nachricht von Anton gelesen, hat aber noch nicht die von Charly gelesen und schreibt Mir gehts gut!. Kurz darauf, ebenfalls noch, bevor sie die Nachricht von Charly empfangen hat, schreibt sie hinterher Richtig gut sogar!. Im folgenden sind für obenstehendes Szenario mehrere Beispiele angegeben, wie Anton, Berta und Charly ihre Nachrichten in ihrem Chatfenster sehen. Geben Sie jeweils an, ob die Reihenfolge dabei - eine totale Ordnung darstellt (total) - keine totale Ordnung darstellt, aber mit der Kausalordnung verträglich ist (kausal) - keine totale Ordnung darstellt, nicht mit der Kausalordnung verträglich ist, aber die FIFO- Reihenfolge einhält (FIFO) - weder eine totale Ordnung darstellt, noch mit der Kausalordnung verträglich ist, noch die FIFO-Reihenfolge einhält (ungeordnet) Beispiel 1 Beispiel 2 Beispiel 3 Beispiel 4 Beispiel 5 Beispiel 6 Chatfenster von A Chatfenster von B Chatfenster von C Jede richtige Antwort gibt 3 Punkte. Für falsche Antworten gibt es keinen Punktabzug. Wenn Sie die Antwort nicht wissen, dann raten Sie! Kreuzen Sie jedoch nur ein Feld pro Zeile an. Beispiel 1 Beispiel 2 Beispiel 3 Beispiel 4 Beispiel 5 Beispiel 6 total kausal FIFO ungeordnet
Aufgabe 3 (insgesamt 15 Zusatzpunkte) Aus der Vorlesung ist die Klasse ArrayQueue bekannt. Bei untenstehender Implementierung ist es problematisch, wenn zwei Threads gleichzeitig die Methode enqueue() ausführen. Wir nehmen dabei aus Gründen der Einfachheit an, dass jede Zeile Java-Code unteilbar ist. public class ArrayQueue<E> implements Queue<E> { E[] values; int front = 0; int rear = 0;... public void enqueue(e elem) throws QueueOverflow {... public boolean isempty() { return (rear==front); front rear 63 28 44 41 3a) (7 Zusatzpunkte) Angenommen, zwei Threads, Thread1 und Thread2 erhalten ihre Zeitfenster so zugeteilt, dass sich die untenstehende Ausführungsreihenfolge ergibt. Was für eine Folge hat dies für die Datenstruktur, wenn die Queue noch mindestens zwei freie Plätze enthält? Formulieren Sie Ihre Antwort allgemein und nicht anhand des obigen Beispiels. Thread 1 Thread 2 Nur der Wert aus Thread 2 ist eingefügt, statt des Wertes aus Thread 1 ist ein undefinierter Wert eingefügt.
3b) (8 Zusatzpunkte) Im Fall, dass es vor den Aufrufen nur noch einen freien Platz in der Queue gab, können zwei gleichzeitige Aufrufe von enqueue() aus zwei Threads dazu führen, dass anschließend die Schlange leer ist. Füllen Sie die untenstehende Tabelle mit einer Ausführungsreihenfolge aus, die dazu führt, dass anschließend die Schlange leer ist, also der Aufruf von isempty() true zurückgeben würde, sich aber beide einzufügenden Werte im Feld values befinden. Thread 1 Thread 2
Aufgabe 4 (10 Punkte) Schreiben Sie in Prolog eine Regel mehralseinelement(l) die wahr ist, genau dann, wenn L eine Liste mit mehr als einem Element ist. Dabei soll nicht die Länge des Liste ermittelt und mit 1 verglichen werden, so dass die Auswertung auch bei sehr langen Listen noch effizient ist. mehralseinelement([_,_ _]). Aufgabe 5 (15 Punkte) Schreiben Sie in Haskell eine Funktion inorder :: (Ord a) => BinSearchTree a -> [a] die eine Liste zurückgibt, die alle Elemente eines binären Suchbaums in Inorder-Reihenfolge enthält. Zur Erinnerung: data (Ord a) => BinSearchTree a = Empty Node (BinSearchTree a) a (BinSearchTree a) inorder Empty = [] inorder (Node l r) = inorder l ++ [] ++ inorder r
Aufgabe 6 (10 Punkte) Betrachten Sie den untenstehenden binären Suchbaum. Um eine effizientere Implementierung des Iterators in Java zu ermöglichen, soll er in einen gefädelten Baum umgewandelt werden. Zeichnen Sie die benötigten Fäden in diesen Baum ein. Zur Erinnerung: Fäden führen von Knoten, die kein rechtes Kind haben, zum Nachfolger in der Inorder-Reihenfolge. 35 22 41 17 28 44 24 42 48 45
Aufgabe 7 (insgesamt 12 Punkte) Aufgabe 7.1 (6 Punkte) Fügen Sie in den untenstehenden binären Suchbaum den Wert 15 ein. Zeichnen Sie den dadurch entstandenen Baum! Fügen Sie anschließend den Wert 26 ein. Zeichen Sie erneut den dadurch entstandenen Baum. Aufgabe 7.2 (6 Punkte) Geben Sie für den Ursprungsbaum sowie für den Baum, der nach dem Einfügen der 15 entstanden ist, und für den Baum, der nach Einfügen der 15 und der 26 entstanden ist, an, ob er die AVL- Eigenschaft erfüllt oder nicht. Jede richtige Antwort gibt dabei 2 Punkte. Für falsche Antworten gibt es keinen Punktabzug. Wenn Sie die Antwort nicht wissen, dann raten Sie! 24 Erfüllt AVL- Eigenschaft JA NEIN 18 31 Ursprungsbaum 22 27 36 Nach Einfügen der 15 21 25 34 Nach Einfügen der 15 und der 26 Binärer Suchbaum nach Einfügen der 15: Binärer Suchbaum nach Einfügen der 15 und der 26: 24 24 18 31 18 31 15 22 27 36 15 22 27 36 21 25 34 21 25 34 26
Aufgabe 8 (15 Zusatzpunkte) In der Vorlesung wurden Deques (Double-Ended-QUEues) kurz vorgestellt, das sind Schlangen, bei denen man an beiden Enden Elemente anstellen und entfernen kann. Schreiben Sie für die Klasse LinkedDeque, die Deques als doppelt verkettete Liste implementiert, die Methode appendfront(). Alle Methoden stellen sicher dass, wenn der Deque leer ist sowohl front als auch rear auf null zeigen und dass, wenn der Deque nicht leer ist, weder front noch rear auf null zeigen. public class LinkedDeque<E> implements Deque<E> { Cell<E> front = null; Cell<E> rear = null;... public interface Deque<E> { void appendfront(e elem) throws DequeOverflow; void appendrear(e elem) throws DequeOverflow; E removefront() throws DequeUnderflow; E removerear() throws DequeUnderflow; E getfront() throws DequeUnderflow; E getrear() throws DequeUnderflow; boolean isempty(); public class Cell<E> { E value; Cell<E> net; Cell<E> prev; public Cell(E value, Cell<E> net, Cell<E> prev) {... front rear 14 42 22 17 25 public void appendfront(e elem) { if (front==null) { front = rear = new Cell<E> (elem, null, null); else { front = new Cell<E> (elem, front, null); front.net.prev=front;