14. Übungsblatt zu Programmierung, WS 04/05

Werbung
IS
S
SA
R
14. Übungsblatt zu Programmierung, WS 04/05
S
UN
E R SIT
A
IV
A VIE N
Prof. Dr. Gert Smolka, Dipl.-Inform. Guido Tack
http://www.ps.uni-sb.de/courses/prog-ws04/
Lesen Sie im Skript: Kapitel 13
Aufgabe 14.1 Zu welchem Wert evaluiert der Ausdruck ref 1 = ref 1 ? Begründen
Sie ihre Antwort.
Aufgabe 14.2 (Generatoren) Ein Generator für eine Folge x1 , x2 , . . . von Werten
eines Typs t ist eine Prozedur unit → t, die beim n-ten Aufruf xn liefert.
a) Schreiben Sie einen Generator nextSquare für die Folge 0, 1, 4, 9, . . . der Quadratzahlen.
b) Schreiben Sie eine Prozedur newNextSquare : unit → unit → int, die bei jedem Aufruf einen neuen Generator für die Folge der Quadratzahlen liefert.
c) Schreiben Sie eine Prozedur newGenerator : (int → α) → unit → α, die zu einer
Prozedur f einen Generator für die Folge f 0, f 1, f 2, . . . liefert.
d) Schreiben Sie eine Prozedur newNextPrime : unit → unit → int, die bei jedem Aufruf einen neuen Generator für die Folge 2, 3, 5, 7, . . . der Primzahlen liefert.
2005–02–09
14:04
Aufgabe 14.3 (Binäre Suche)
Eine Reihung des Types int array heißt sortiert, wenn ihre Komponenten aufsteigend sortiert sind. Schreiben Sie eine Prozedur member : int array → int → bool, die
zu einer sortierten Reihung a und einer Zahl x entscheidet, ob eine Komponente von
a den Wert x hat. Für Reihungen der Länge n soll member die Laufzeit O(log n) haben.
Die logarithmische Laufzeit läßt sich mithilfe einer Technik erreichen, die als binäre
Suche bezeichnet wird. Dafür stellen wir uns die sortierte Reihung als eine Folge vor,
die von links nach rechts läuft, und gehen wie folgt vor:
1. Bestimme einen Index m, der etwa in der Mitte der Reihung liegt.
2. Wenn x der Wert der m-ten Komponente ist, liefere true.
3. Wenn x kleiner als der Wert der m-ten Komponente ist, suche in der linken Teilreihung weiter.
4. Wenn x größer als der Wert der m-ten Komponente ist, suche in der rechten
Teilreihung weiter.
5. Wenn die zu durchsuchende Teilreihung leer ist, liefere false.
Eine Teilreihung können wir durch das Paar aus ihrem kleinsten und größten Index
darstellen.
Aufgabe 14.4 Sie sollen eine Prozedur rotate : α array → unit schreiben, die die Komponenten einer nichtleeren Reihung um eine Position nach rechts schiebt. Dabei soll
die letzte Komponente an die Stelle der ersten Komponente rücken.
a) Schreiben Sie rotate mithilfe einer iterativ rekursiven Hilfsprozedur rotate 0 .
b) Schreiben Sie rotate mithilfe einer Schleife.
Aufgabe 14.5 Geben Sie eine möglichst kleine gewurzelte Listenstruktur an, die
zwei verschiedene Knoten enthält, die denselben Zustand haben.
Aufgabe 14.6 Wir betrachten Listenstrukturen mit Marken aus int und nennen einen
Knoten sortiert, wenn er azyklisch ist und seine Liste aufsteigend sortiert ist. Schreiben Sie eine Prozedur enter : int node → int → unit, die in die Listenstruktur eines
sortierten Knotens v einen neuen Knoten mit der Marke x so einfügt, dass v weiterhin sortiert ist.
Aufgabe 14.7 Schreiben Sie eine Prozedur circle : int → intnode, die zu n ≥ 1 eine
zyklische Listenstruktur der Form
1
2
2005–02–09
...
14:04
n
erzeugt. Als Ergebnis soll der mit 1 markierte Knoten geliefert werden.
Aufgabe 14.8 Schreiben Sie eine Prozedur nodes : α node → α node list, die alle von
einem Knoten aus erreichbaren Knoten liefert. Die Prozedur soll auch für zyklische
Knoten funktionieren. Verwenden Sie eine Hilfsprozedur nodes 0 , die sich in einem
Akkumulatorargument alle besuchten Knoten merkt. Geben Sie die Laufzeit Ihrer
Prozedur an.
Aufgabe 14.9 Schreiben Sie eine Prozedur iscircle : α node → bool, die testet, ob ein
Knoten auf einem Zyklus liegt. Vorsicht: Nicht jeder zyklische Knoten liegt auf eiem
Zyklus. Die Laufzeit von iscircle soll linear bezüglich der Größe der Listenstruktur
des Knotens sein.
Aufgabe 14.10 (Effiziente imperative Schlangen) Schreiben Sie eine Struktur, die
imperative Schlangen gemäß der folgenden Spezifikation realisiert:
eqtype ’a queue
val queue : unit → ’a queue
val insert : ’a * ’a queue → unit
val head
: ’a queue → ’a
(* Empty *)
val remove : ’a queue → unit
(* Empty *)
val empty : ’a queue → bool
Die Operation queue liefert eine neue Schlange, die noch keine Einträge enthält. Die
Operation insert trägt einen Wert in eine Schlange ein. Die Operation head liefert
den ältesten Eintrag in einer Schlange. Die Operation remove entfernt den ältesten
Eintrag aus einer Schlange. Die Operation empty testet, ob eine Schlange Einträge
enthält.
Alle Operationen sollen konstante Laufzeit haben.
Sie sollen die Schlangen mithilfe einer Listenstruktur realisieren, die die in der Schlange stehenden Einträge enthält. Eine imperative Schlange soll durch ein Paar
(v, r) : α node ∗ α node ref
wie folgt dargestellt werden: (1) Die Liste des Knoten v besteht aus den in der Schlange stehenden Einträgen, wobei der älteste Eintrag ganz vorne und der jüngste Eintrag ganz hinten steht; (2) Die Referenz r zeigt auf den letzten Knoten der mit v
beginnenden Listenstruktur.
2005–02–09
14:04
Herunterladen