Organisatorisches 1 Wiederholung

Werbung
Bäume
Programmierstarthilfe WS 2010/11
Fakultät für Ingenieurwissenschaften und Informatik
Organisatorisches
Im Web unter http://www.uni-ulm.de/psh
Vorwissen
Du kannst mit Objekten umgehen und hast bereits mit verketteten Listen gearbeitet.
Konzepte
Auf diesem Blatt werden wir einen binären Suchbaum anlegen, dieser erweitert die Ideen verketteter Listen um die schnelle Auffindbarkeit von Elementen. Wir werden dabei sehen, dass rekursive
Methoden praktisch und effizient zugleich sein können.
1 Wiederholung
Zur Wiederholung des Vorwissens findest du hier Aufgaben, die du am besten schriftlich und direkt
auf dem Blatt löst. Versuche zunächst, ob du die Lösung auswendig kennst.
1.1 Listen
Vervollständige die Methode swap(Node a) der Klasse List. Sie soll das übergebene Element a
mit seinem Nachfolger in der Liste vertauschen. Beispiel: Aus der Liste d-e-f-g-a–b-c würde durch
Ausführen der Methode swap(a) die Liste d-e-f-g–b-a-c. Die Methode soll in jedem Fall funktionieren, also auch wenn das Element a das erste oder letzte der Liste ist, keinen Nachfolger hat oder
nicht in der Liste enthalten ist.
1
2
3
4
public class Node{
public int value;
public Node nf;
}
//Nachfolger
5
6
7
public class List{
public Node kopf;
8
9
public void swap(Node a) {
Programmierstarthilfe
//TODO:
10
Bäume
Node a mit seinem Nachfolger vertauschen
11
}
12
13
}
2 Aufgaben
2.1 Binäre Suchbäume
Schreibe eine Klasse BinBaumKnoten, mit der sich Knoten eines binären Suchbaums erstellen
lassen. Jeder Knoten enthält einen int-Wert und Referenzen auf einen linken und einen rechten Nachfolgerknoten vom gleichen Typ. Du kannst dich dabei an der Liste vom letzten Mal orientieren.
Schreibe außerdem eine Klasse BinBaum, die eine Referenz auf die Wurzel des Binärbaums enthält.
a) Schreibe einen Konstruktor für die Klasse BinBaumKnoten, der einen int-Wert übergeben
bekommt und einen Knoten mit entsprechendem Wert anlegt.
b) Schreibe einen Konstruktor für die Klasse BinBaum, der einen int-Wert übergeben bekommt
und einen neuen Baum erzeugt, dessen Wurzel ein Knoten mit dem übergebenen Wert erstellt.
c) Schreibe eine rekursive Einfügemethode für die Klasse BinBaum. Sie bekommt einen intWert übergeben. Ist der Wert kleiner als der der Wurzel ruft sie sich rekursiv auf, allerdings mit
dem linken Nachfolgerknoten, ansonsten mit dem rechten. Ist der entsprechende Nachfolger
null wird an dieser Stelle ein neuer Knoten mit dem entsprechenden Wert eingefügt. Ist der
Wert schon vorhanden, soll kein neuer Knoten eingefügt werden und false zurückgegeben
werden.
d) Schreibe eine Methode boolean contains(int wert), die überprüft ob ein IntegerWert im Baum vorhanden ist. Bei der Suche kannst du dich an der vorherigen Teilaufgabe
orientieren. Die Methode soll rekursiv arbeiten.
e) Schreibe für die Klasse BinBaum die rekursiven Methoden
String preOrder(), String postOrder() und String inOrder(), welche
den Baum in gegebener Weise traversieren (durchlaufen) und alle Werte als String mit Leerzeichen dazwischen ausgeben.
2.2 Binäre Suchbäume 2
Die Klasse BinBaum soll nun um weitere Methoden erweitert werden. Teste diese mit einem selbst
erstellten Binärbaum.
a) Schreibe eine Methode für den Binärbaum, welche den Knoten mit dem kleinsten Wert im
Binärbaum sucht und dessen Wert zurückgibt.
int smallestNode().
2
Programmierstarthilfe
Bäume
b) Schreibe eine Methode int countLeaves(), welche die Anzahl der Blattknoten zählt
und zurück gibt.
c) Schreibe zur Ausgabe des Binärbaum eine Methode void printOut(), die diesen rekursiv auf der Konsole ausgibt. Die Ausgabe könnte etwa so aussehen (der Baum ist also um 90
Grad nach links gedreht):
10
7
6
5
4
3
1
Tipp: Vernachlässige zuerst die Einrückung.
*d) Schreibe eine Methode BinBaum copy(), welche eine tiefe Kopie des Binärbaums zurückgibt. Tiefe Kopie bedeutet, dass keine Referenzen des alten Baums verwendet, sondern neue
eigene BinBaumKnoten erzeugt werden.
*e) Entwickle eine Methode void deleteNode(int wert), welche den Knoten mit dem
gegebenen Wert löscht und dafür sorgt, dass die Ordnung des neuen Binärbaums gewährleistet
bleibt.
(* = schwierige Aufgabe)
3 Bonusaufgaben
Durch die Aufgaben oben hast du ein Verständnis für das neue Konzept dieses Blatts bekommen.
Durch Bonusaufgaben kannst du nun deine Kenntnisse vertiefen.
3.1 Huffman-Kodierung
Statt einen Text (wie Huffman“) Buchstabe für Buchstabe mit jeweils 8 Bit abzuspeichern1 , kann
”
man ihn kürzer speichern, indem man eine Kodierung nutzt 2 . Dabei wird ausgenutzt, dass nicht alle
Buchstaben des Alphabets (oder gar tausende Sonderzeichen) im Text vorkommen und dass manche
Buchstaben häufiger vorkommen als andere (z.B. hier f“).
”
Eine beliebte Kodierung ist die sog. Huffman- oder Shannon-Fano-Kodierung3 , die auch in einigen
ZIP-Formaten eingesetzt wird.
Wir wollen nun einen Huffman-kodierten Text dekodieren:
10110110110111101101101101000001101101“
”
1 etwa
als 0000011101001000011101010110011001100110011011010110000101101110“ in UTF-8
”
als 110001010011111010“ mittels Huffman-Kodierung
”
3 siehe auch
http://de.wikipedia.org/wiki/Shannon-Fano-Kodierung
2 etwa
3
Programmierstarthilfe
Bäume
Die Dekodierung läuft entlang des untenstehenden Baumes: Wir beginnen an der Wurzel. Die erste 1“ im Text bedeutet, dass wir im Baum nach rechts weitergehen sollen. Dann kommt eine 0“
”
”
und heißt, dass wir nach links weitergehen sollen. Wir haben dann ein Blatt erreicht, das mit dem
Buchstaben B“ beschriftet ist. B“ ist damit der erste Buchstabe des dekodierten Textes (im kodier”
”
ten Bitstring durch nur 2 Bit dargestellt). Wir gehen dann zurück an die Wurzel wiederholen den
Vorgang vom 3. Bit an.
Schreibe ein Programm, in dem der folgende Baum fest eingebaut ist und mit dem du den Text
dekodieren kannst.
4
Herunterladen