Sie sind auf Seite 1von 38

Stefan Schmitz, Matthias Kloss, Matthias Witaßek

Huffman Code Applet


Dokumentation
Stand vom 26.04.2001
Huffman Code Applet 03.05.01

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 2


Huffman Code Applet 03.05.01

Abstract

Der Huffman Code ist ein verlustfreier Kompressionsalgorithmus. Er erzeugt optimale


Kodewortlängen unter Berücksichtigung der Häufigkeit der einzelnen zu kodierenden Zeichen. Das
bedeutet, häufig vorkommende Zeichen werden mit kurzen Bitfolgen kodiert, seltene mit längeren.
Auf diese Weise kann maximal komprimiert werden. Diese Erzeugung geschieht mit Hilfe eines
Kodebaumes.
Weiterhin wird durch die Präfix-Eigenschaft des Huffman Codes sichergestellt, dass die
Dekodierung eindeutig ist.

Das Huffman Code Applet nun ist eine Verständnishilfe für die Vorgehensweise des Huffman Code.
Insbesondere können mit diesem Applet die einzelnen Schritte bei der Erstellung des Kodebaumes
und der Generierung der Kodeworte verfolgt werden. Die Geschwindigkeit legt dabei allein der
Benutzer fest, auch gibt er den zu kodierenden Text vor.

Angezeigt werden neben dem zu kodierenden Text:


• Wahrscheinlichkeit der einzelnen Zeichen
• Kodierung jedes einzelnen Zeichens
• Kodebaum
• Vollständig kodierter Text in Binärform
• Kompressionsgrad.

Das Applet ist in Java erstellt worden und kann entweder mit dem Appletviewer (im Java
Development Kit enthalten) oder in einem Browser gestartet werden. Zu beachten ist dabei, dass
das Java-Plugin des Browsers (also die Java-VM) mindestens in der Version 1.2 installiert sein
muss.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 3


Huffman Code Applet 03.05.01

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 4


Huffman Code Applet 03.05.01

Inhaltsverzeichnis

Abstract 3
Inhaltsverzeichnis 5
Einleitung 7
Anwendung 8
Voraussetzungen 8
Start 8
Benutzung 9
Design 11
Use Cases 13
Huffman kodieren 13
Kodieren 14
Anzeigen 15
Wahrscheinlichkeit der Zeichnen errechnen 15
Kodierung für Zeichen bestimmen 15
Nächsten Knoten anzeigen 16
Testergebnisse 17
Systeme 17
Bekannte Bugs 17
Ausblick 18
Stufenloser Zoom 18
Sortierung der Legende 18
Klasse HuffmanCodec 19
Inhalt 19
Konstanten 19
Funktionen 20
Öffentlich 20
Privat 20
Klassen VisualNode 22
Inhalt 22
Attribute 22
Konstruktor 23
Methoden 23
Klasse VisualTree 24
Inhalt 24
Attribute 25
Konstruktor 25
Methoden 25
Klasse Controller 27
Inhalt 27
Attribute 27
Konstruktor 28
Methoden 28
Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 5
Huffman Code Applet 03.05.01

Klasse Zeichen 30
Inhalt 30
Attribute 30
Konstruktor 30
Methoden 30
Klasse NotEnoughLettersException 32
Inhalt 32
Konstruktor 32
Klasse huffman 33
Inhalt 33
Attribute 33
Konstruktor 34
Methoden 34
Klasse UpperCaseField 36
Inhalt 36
Attribute 36
Konstruktor 36
Klasse TreePanel 37
Inhalt 37
Attribute 37
Konstruktor 37
Methoden 38

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 6


Huffman Code Applet 03.05.01

Einleitung
Das Huffman Code Applet soll verdeutlichen, wie die Huffmankodierung funktioniert. Dabei
werden grundlegende Kenntnisse der Informatik vorausgesetzt. Als Beispiel sollten sowohl
Binärbäume als auch ASCII-Codes bekannt sein.

Dieses Applet ist sowohl für Studenten (zum Verständnis) als auch für Dozenten (zur Demonstration
während der Vorlesung) gedacht.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 7


Huffman Code Applet 03.05.01

Anwendung
Voraussetzungen
Das Huffman Code Applet ist in Java implementiert und daher weitgehend systemunabhängig.
Lediglich eine Java Virtual Machine (JavaVM) in der Version 1.2 oder höher sowie ein Browser mit
diesem Plugin werden benötigt.

Start
Das Applet wird gestartet, indem die Datei huffman.html in den Browser geladen wird. Dieser
startet automatisch das Java-Plugin und die O berfläche des Applets erscheint.

Huffman Code Applet im Internet Explorer

Alternativ kann das Huffman Code Applet auch mit dem Appletviewer aus dem JDK ausgeführt
werden. Hierfür muss jedoch eine modifizierte HTML-Datei benutzt werden, da der Appletviewer
keine relativen Größenangaben unterstützt. Der Aufruf muss folgendermaßen aussehen:
appletviewer huffman_appletviewer.html

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 8


Huffman Code Applet 03.05.01

Es existiert noch ein dritte Möglichkeit, das Applet zu starten. Dafür muss auf dem System Java
derart installiert sein, dass die Dateiendung .jar mit der JavaVM verknüpft ist. Auf diese Weise
genügt ein Doppelklick auf HuffmanCodecApplet.jar.

Benutzung
Vom Benutzer muss nun eine Zeichenkette eingegeben werden, die kodiert werden soll. Diese ist
auf eine Länge von 30 Zeichen begrenzt, da sonst die Baumdarstellung riesenhafte Ausmaße
annehmen kann und schlichtweg nicht mehr übersichtlich ist.

Nach der Eingabe wird der Kodierungsprozeß gestartet, indem man auf den Button draw tree
klickt. Es erscheint der komplette Kodebaum. Gleichzeitig wird die Legende mit den Zeichen, deren
Wahrscheinlichkeiten und deren Binärkodierung gefüllt. Die daraus resultierende binäre
Zeichenkette wird im Feld cipherText angezeigt. Dabei wird zwischen der binären Darstellung
zweier Zeichen Platz gelassen, der besseren Lesbarkeit wegen.
Weiterhin wird der Kompressionsgrad angegeben, der aus dem Verhältnis zwischen Länge des
Eingabetextes und Länge das Kodetextes errechnet wird. Je größer dieser Grad, desto besser die
Komprimierung.

Huffman Code Applet im Appletviewer

Um den Aufbau des Baumes schrittweise verfolgen zu können, müssen die Buttons „draw previous“
und „draw next“ verwendet werden. Dabei dient „draw previous“ dazu, zum vorherigen Schritt
zurück zu gehen, während man mit „draw next“ – welch Wunder – den nächsten Schritt dargestellt
bekommt.
Um den Aufbau von Anfang an zu sehen, löscht man zunächst mit der Schaltfläche „clear tree“ das
Anzeigefeld für den Baum. Danach wird mit jedem Klick auf „draw next“ die Zusammenfassung

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 9


Huffman Code Applet 03.05.01

der zwei niedrigstwahrscheinlichen Knoten zu einem neuen Knoten dargestellt. Der Baum wird
sequentiell aufgebaut.

Schrittweise Anzeige im Internet Explorer

Hat man den eingegebenen Text satt und möchte lieber einen anderen probieren, so ist dies
denkbar einfach zu erledigen: Den neuen Text anstelle des alten eintippen. Der Baum wird
automatisch neu erstellt, sobald man wieder auf „draw tree“ drückt.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 10


Huffman Code Applet 03.05.01

Design

Das Huffman Codec Applet ist in drei logische Module gegliedert, dem objektorientierten Ansatz
Model-View-Controller (MVC) folgend:

• Huffman Codec (Implementierung durch Matthias Witaßek)


Erstellung des kodierten String sowie des zugehörigen Kodierungsbaumes.

• grafische Darstellung (Implementierung durch Matthias Kloss)


Gesamte grafische Oberfläche inklusive Zeichnen des Kodierungsbaumes.

• Schnittstelle Codec – Darstellung und Steuerung (Implementierung durch Stefan Schmitz)


Kommunikation zwischen Model und View, Steuerung der Darstellung

Für die optimale grafische Darstellung des Kodebaumes wird ein normalisiertes Koordinatensystem
(Kantenlänge in x- und y-Richtung ist 1) benutzt. Die sich aus dem Kodierungsbaum ergebenden
Positionen eines jeden Knotens werden bereits im Huffman-Codec festgelegt.

Nachfolgend ist ein UML-Diagramm der Klassenbeziehungen dargestellt.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 11


Huffman Code Applet 03.05.01

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 12


Huffman Code Applet 03.05.01

Use Cases

Huffman kodieren
Name des UseCase Huffman kodieren
Beteiligte UseCase Kodieren
Anzeigen
Aktor Bediener
Kurzbeschreibung Kodierung der eingegebenen Zeichenketten und Ausgabe
des Kodebaumes
Auslöser Programmstart
Ergebnisse Ausgabe des Kodebaum mit Kodierung der einzelnen
Zeichen
Arbeitsschritte 1. Eingabe Zeichenkette
2. Starten der Kodierung
3. Darstellung des Kodebaumes
4. Nächstes Zeichen darstellen
Sonderfälle S1. Eingabe ist leer
Erläuterungen Arbeitsschritt wird solange wiederholt bis Baum komplett
aufgebaut ist
Bemerkungen

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 13


Huffman Code Applet 03.05.01

Kodieren
Name des UseCase Kodieren
Beteiligte UseCase Wahrscheinlichkeit der Zeichen errechnen
Kodierung für Zeichen bestimmen
Aktor Bediener
Kurzbeschreibung Durchführung des Algorithmus zur Huffmankodierung
Auslöser Arbeitschritt 2. UseCase Huffman kodieren
Ergebnisse Tabelle die den Codetree darstellt
Arbeitsschritte 1. Ermittlung der Zeichen im Eingabezeichen und deren
Wahrscheinlichkeit
2. Berechnung des Optimalkodes nach Huffman
3. Eintragung in Tabelle
Sonderfälle -
Erläuterungen -
Bemerkungen -

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 14


Huffman Code Applet 03.05.01

Anzeigen
Name des UseCase Anzeigen
Beteiligte UseCase Nächsten Knoten Anzeigen
Aktor Bediener
Kurzbeschreibung Anzeigen der Bildschirmelemente
Auslöser Arbeitsschritt 3. UseCase Huffman kodieren
Ergebnisse Visualisierung des Kodebaumes auf dem
Bildschirm
Arbeitsschritte 1. Aufbau des Zeichenbaumes
2. Nächstes Zeichen anzeigen
Sonderfälle -
Erläuterungen -
Bemerkungen -

Wahrscheinlichkeit der Zeichnen errechnen


Name des UseCase Wahrscheinlichkeit der Zeichnen errechnen
Beteiligte UseCase -
Aktor Bediener
Kurzbeschreibung Errechnet die Häufigkeit der Zeichen in der
Eingabezeichenkette
Auslöser Arbeitsschritt 1. UseCase kodieren
Ergebnisse Wahrscheinlichkeit der Zeichen
Arbeitsschritte 1. Anzahl verschiedener Zeichen ermitteln
2. Für jedes Zeichen die Häufigkeit bestimmen
3. Relative Häufigkeit errechnen
Sonderfälle
Erläuterungen
Bemerkungen

Kodierung für Zeichen bestimmen


Name des UseCase Kodierung für Zeichen bestimmen
Beteiligte UseCase -
Aktor Bediener
Kurzbeschreibung Ermittelt Optimalkode nach Huffman für jedes
Zeichen in Eingabezeichenkette
Auslöser Abeitschritt 2. UseCase kodieren
Ergebnisse Optimalkode
Arbeitsschritte 1. 2 Zeichen mit der geringsten
Wahrscheinlichkeit ermitteln
2. Bilden eines neuen Knotens aus den beiden
Zeichen mit Summe der Wahrscheinlichkeit
Sonderfälle
Erläuterungen Arbeitschritte 1. u. 2. Werden wiederholt, bis nur
noch ein Zeichen (Hauptknoten) übrigbleibt
Bemerkungen

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 15


Huffman Code Applet 03.05.01

Nächsten Knoten anzeigen


Name des UseCase Nächsten Knoten anzeigen
Beteiligte UseCase -
Aktor Bediener
Kurzbeschreibung Stellt den nächsten Knoten auf dem Bildschirm
dar
Auslöser Arbeitschritt 2. UseCase Anzeigen
Ergebnisse Nächster Knoten wird dargestellt
Arbeitsschritte 1. Ermitteln der Blätter des neuen Knotens
2. Position bestimmen
3. Neuen Knoten zeichnen
Sonderfälle S1. Alle Knoten gezeichnet
Erläuterungen
Bemerkungen

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 16


Huffman Code Applet 03.05.01

Testergebnisse
Systeme
Das Huffman Code Applet wurde unter folgenden Systemen erfolgreich getestet:

• Windows 98 mit Internet Explorer 5.5


• Windows 98 mit Netscape 4.7 und nachträglich installierten Java 1.2 Plugin
• Windows 98 mit JDK Appletviewer
• Linux mit JDK Appletviewer

Bekannte Bugs
• Unvollständige Anzeige des cipherText
Manchmal ist der binärkodierte Text nicht oder nur teilweise sichtbar.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 17


Huffman Code Applet 03.05.01

Ausblick

Folgende Erweiterungen / Verbesserungen des Applets sind denkbar:

Stufenloser Zoom
Der Verkleinerungsgrad bei der Ansicht des Kodebaumes ist bis jetzt mit einer unteren Schranke
festgelegt, so dass die Knoten nie ein gewisse Pixelgröße unterschreiten. Das hat jedoch den
Nachteil, dass sehr große Bäume sehr unübersichtlich dargestellt werden. Abhilfe würde hier eine
stufenlose Zoomfunktion schaffen, die zudem noch durch den Benutzer selbst gesteuert werden
kann. Auf diese Weise kann er sich den Baum nach seinen Wünschen zurecht rücken, Screenshots
werden auch bei großen Bäumen möglich.

Sortierung der Legende


Dem Benutzer kann ermöglicht werden, die Sortierung der Legende nach einer von ihm gewählten
Spalte vorzunehmen. Das kann durch einen Klick auf den jeweiligen Spaltenkopf geschehen.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 18


Huffman Code Applet 03.05.01

Klasse HuffmanCodec

Inhalt
Für dieses Dokument wird vorausgesetzt, dass dem Leser die Funktionsweise der
Huffmankodierung bekannt ist.

HuffmanCodec erstellt aus einem gegebenen String den Huffmanbaum und ermittelt die
Zeichenkodierungen. Beides wird mit Hilfe der Interface-Klassen VisualTree und
VisualNode an den Controller übergeben. Der String darf nur aus ASCII-Zeichen bestehen.
Der Baum wird bereits bei der Instanziierung dieser Klasse berechnet.

Weiterhin werden die Koordinaten der Knoten des Baumes, die später für die Darstellung
benötigt werden, durch HuffmanCodec festgelegt. Dafür werden normalisierte Koordinaten
benutzt, die sich im Intervall [0.0, 1.0] befinden. Auf diese Weise kann der Baum in jeder
Auflösung dargestellt werden. Die dafür nötigen Punkte errechnet man durch Multiplikation
der normalisierten Koordinaten mit der gewünschten maximalen Auflösung.

Konstanten
BO RDERX Legt die rechte Intervallgrenze der normalisierten
Koordinaten für die x-Achse fest. Standardwert ist 1.0.

MAXCHARS Maximale Anzahl verschiedener Zeichen, die der


Eingabestring enthalten darf. Da hier mit dem ASCII-
Zeichensatz gearbeitet wird, ist der Standardwert 255.

MAXLENGTH Beinhaltet die maximal erlaubte Länge des Eingabestrings.


Standardmäßig ist hier der Wert 255 eingetragen.

MAXNODS Maximale Anzahl der Knoten, die der Huffmanbaum


enthalten darf. Der Wert ist abhängig von der Länge des
Eingabestrings und der Anzahl unterschiedlicher Zeichen.
Als Default ist er mit 1024 belegt.

NODEDISTANCEFACTO R Mit jeder Ebene, um die ein Baum nach unten wächst, muss
er auch steiler werden. Sonst würden sich Knoten
überlappen, weil sie sich an der gleichen Position befinden.
Diese Erhöhung des Baumgefälles mit jeder neuen Ebene
wird duch NODEDISTANCEFACTO R gesteuert. Dabei wird
das Gefälle jedesmal mit diesem Faktor multipliziert. Der
Standardwert 2 bewirkt somit jeweils eine Verdopplung des
Gefälles.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 19


Huffman Code Applet 03.05.01

Funktionen
Öffentlich
HuffmanCodec(String input)

Konstruktor, der zugleich den gesamten Baum mitsamt normalisierten Koordinaten


aus dem Eingabestring input erstellt.
Dazu wird zunächst der Baum mit der Funktion calculateHuffmanTree() erstellt.
Anschließend wird über determineCode() die binäre Darstellung jedes Zeichens im
Baum ermittelt. Danach werden die normalisierten Koordinaten errechnet unter
Berücksichtigung der oben definierten Konstanten berechnet (calculatePositions()).
Sollte dabei ein Überlappung von Knoten auftreten (isO verlapDetected()), wird der
ebenfalls normalisierte Radius eines Knotens entsprechend verringert.

VisualTree getTree()

Liefert den erstellten Huffmanbaum als VisualTree.

float getRadius()

Liefert den normalisierten Radius aller Knoten im Huffmanbaum.

Privat
VisualTree calculateHuffmanTree(String input)

Erstellt den Huffmanbaum aus input. Dazu wird zunächst für jedes Zeichen in input,
für das noch kein Knoten existiert, einer angelegt. Gab es den Knoten bereits, wird
die Häufigkeit dieses Zeichens (entspricht dem Gewicht) erhöht. Auf diese Weise
erhält man eine unsortierte Liste von Knoten, die keinerlei Beziehungen zueinander
haben. Für jedes Zeichen dieser Knoten ist die Häufigkeit ermittelt worden.

Im nächsten Schritt wird aus dieser Liste der Baum mit den Beziehungen der Knoten
untereinander erstellt.
Dazu wird die vorhandene Liste nach aufsteigender Häufigkeit der Zeichen sortiert.
Anschließend wird aus den zwei geringsthäufigen Knoten ein neuer gebildet, der
deren Vater darstellt. Diesem neuen Knoten werden die beiden als Söhne
untergeordnet. Im nächsten Schleifendurchlauf wird die nun erweiterte Liste erneut
sortiert und die zwei geringsthäufigen Knoten auch wieder einem neuen Vater
untergeordnet. Dieser Vorgang wird so lange wiederholt, bis alle Knoten bearbeitet
wurden, inklusive der neu hinzugefügten. Als Ergebnis steht nun der Huffmanbaum
fest, der zurückgeliefert wird.

determineCode(VisualNode node, String code, float distanceHorizontal,


int distanceVertical, float stepHorizontal)

Über die Methode des rekursiven Abstieges wird aus dem Huffmanbaum der
Binärcode für die einzelnen Zeichen ermittelt. Startpunkt ist die Wurzel (node), der
der String code zugewiesen wird. Mit jeder Verzweigung (es wird einfach dem Pfad
entlang nach unten gefolgt) nach links wird dem Code eine Null hinzugefügt, rechts

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 20


Huffman Code Applet 03.05.01

kommt stattdessen eine Eins dazu. Die Funktion wird für die Kinder, sofern sie
vorhanden sind, rekursiv aufgerufen. Auf diese Weise wird mit zunehmender Tiefe
im Baum auch der Code länger.

Gleichzeitig mit der Ermittlung des Codes werden die Ausmaße des Baumes
bestimmt. Dazu dienen distanceHorizontal (horizontale Ausdehnung) und
distanceVertical (vertikale Ausdehnung). Mit stepHorizontal wird das Gefälle des
Baumes mit zunehmender Tiefe erhöht. Diese Werte entsprechen nicht den
normalisierten Koordinaten, sie dienen allerdings zu deren Bestimmung.

calculatePositions(VisualNode node, int level)

Mit Hilfe der in determineCode() gewonnenen Daten über die Ausdehnung des
Baumes werden hier die normalisierten Koordinaten berechnet. Auch hier kommt
das Prinzip des rekursiven Abstieges zum Einsatz, Startpunkt ist node.
Parallel zur Koordinatenberechnung wird ein zweidimensionales Feld mit den x-
Koordinaten der Knoten gefüllt. Dabei enthält die erste Dimension des Feldes die
Ebene im Baum, auf der sich der Knoten befindet. Die zweite Dimension ist dann
die Koordinate selbst. Dieses Feld wird in isO verlapDetected() zur Feststellung einer
Überlappung benutzt.

boolean isO verlapDetected()

Mit Hilfe des in calculatePositions() erstellten Feldes wird überprüft, ob es


Überdeckungen bei der Darstellung der Knoten geben würde. Ist dies der Fall, wird
als Rückgabewert true geliefert.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 21


Huffman Code Applet 03.05.01

Klassen VisualNode

Inhalt

Die Objekte der Klasse VisualNode stellen die Knoten und Blätter des Baumes (siehe VisualTree)
dar, welcher bei der Huffman-Kodierung entsteht. Bei dem entstehenden Binärbaum entspricht
jedes Blatt einem konkreten Zeichen der Eingabezeichenkette, die Knoten entsprechen einem
virtuellen Zeichen, zusammengesetzt aus den Kindern des Knotens. Die Wahl der Blätter, welche zu
einem Knoten zusammengefaßt werden, hängt von ihrer Häufigkeit im Eingabestring ab, es werden
die mit der geringsten zuerst gewählt. Der so entstehende Knoten ersetzt seine beiden Kinder,
wobei sich die Wahrscheinlichkeit (Wahrscheinlichkeit = Häufigkeit / Anzahl Zeichen) des Knotens
aus der Summe der Wahrscheinlichkeiten der beiden Kinder ergibt. Dieser Vorgang wird solange
fortgesetzt, bis es nur noch einen Knoten (Root) mit der Wahrscheinlichkeit 1 gibt. Die Knoten
entsprechen nach diesem Schema den Blättern, da sie als Blatt des übergeordneten Knotens
angesehen werden können. Deshalb haben Blätter (Zeichen) und Knoten (virtuelle Zeichen)
dieselben Eigenschaften und werden in einer Klasse zusammengefaßt (ein VisualNode-Objekt kann
also die Rolle eines Zeichens und/oder eines Knotens spielen).

Attribute
Folgende Eigenschaften eines VisualNode ergeben sich aus der obigen Beschreibung:

Modifier Typ Name Kurzbeschreibung


protected char codeLetter Entspricht dem Zeichen, welches der
Knoten darstellt. Bei virtuellen
Zeichen bleibt dieses Feld leer.
protected int weight Entspricht der Häufigkeit eines
Zeichens. Diese wurde der
Wahrscheinlichkeit wegen ders
einfacheren
vorgezogen.(Integer↔Float)
protected String code Entspricht dem binären Huffman-
Code für diesen Knoten
protected int parent Index auf die Position des Vater-
knotens. Ist keiner vorhanden (Root)
ist der Wert –1.
protected int leftChild Index auf den linken Sohn. Ist keiner
vorhanden (Blatt) ist der Wert –1.
protected int rightChild Index auf den rechten Sohn. Ist
keiner vorhanden (Blatt) ist der Wert
–1.
protected float xPositonNormal normalisierte x-Koordinate. Wert
liegt zwischen 0.0 und 1.0.
protected float yPositionNormal normalisierte y-Koordinate. Wert
liegt zwischen 0.0 und 1.0.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 22


Huffman Code Applet 03.05.01

Konstruktor
- VisualNode()

Attribute leftChild, rightChild und parent erhalten den Wert –1.

- VisualNode(char c, int w, String s, float x, float y, int lc, int rc, int p)

Parameter: c = codeLetter,
w = weight,
s = code,
x = xPositionNormal,
y = yPositionNormal,
lc = leftChild,
rc = rightChild,
p = parent.

Methoden
Zu jedem der oben aufgeführten Attribute gibt es get- und set- Methoden, wobei sich die
normalisierten Koordinaten durch die Methode setPositionXY() setzen lassen.
Weitere Funktionen sind:

- equals

public boolean equals(VisualNode obj)

Vergleicht den aufrufende VisualNode mit dem Parameter obj, wobei die Gleichheit gilt, wenn
beide Knoten den gleichen codeLetter haben. Bei Gleichheit wird ist der Rückgabewert true.

- hasChildren

public boolean hasChildren()

Liefert den Rückgabewert true, wenn der aufrufende VisualNode Kinder hat. Ein Knoten im
Huffmanbaum hat entweder keine Kinder oder zwei Kinder.

- printNode

public void printNode()

Gibt die Attributswerte auf stdout (normalerweise Bildschirm) aus

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 23


Huffman Code Applet 03.05.01

Klasse VisualTree
Inhalt
Die Klasse VisualTree entspricht einem Container, der alle Objekte des Typs VisualNode speichert.
Sie stellt also den Huffmanbaum dar, dessen Knoten und Blätter VisualNode-Objekte sind. Die
Hierarchie des Baumes wird durch die Position der Elemente und deren Verweise auf Kind- und
Vater-Objekte realisiert. Die Hierarchie und deren Abbildung im Baum stellt sich folgendermaßen
dar. Da der Huffmanbaum von unten aufgebaut wird, sind die ersten beiden Knoten auch die
untersten im Baum (sie werden auch als erstes auf dem Bildschirm gezeichnet!). Es gehören immer
zwei VisualNode-Objekte zusammen, sie sind die beiden Söhne des Knotens, auf den sie mit ihrem
parent-Attribut referenzieren. Sind die ersten beiden Paare und der zugehörige Vaterknoten
gezeichnet, bilden die nächsten beiden Knoten plus ihr Vater das nächste zu zeichnende Tripel.
Dabei ist der erste Knoten immer der Linke, der andere der Rechte. Die Abbildung und die dazu
gehörende Tabelle sollen dies verdeutlichen. Die roten Zahlen sollen nur die Knoten nummerieren
und sind im eigentlichen Programm nicht enthalten, zur Vereinfachung sind in der Tabelle nur die
hier wichtigen Attribute von VisualNode aufgeführt.

Huffmanbaum von "ABCD"

VisualNodeObjekt
KnotenNr.
Index codeLetter leftChild rightChild parent
(rote Ziffer)
(Index) (Index) (Index)
0 3 A -1 -1 5
1 4 B -1 -1 5
2 1 C -1 -1 4
3 2 D -1 -1 4
4 6 2 3 6
5 5 0 1 6
6 7 4 5 -1
Skizze des Speicherabbilds in VisualTree

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 24


Huffman Code Applet 03.05.01

Als Speicherstruktur wurde die Klasse ArrayList gewählt, weil diese dynamisch erweiterbar ist und
trotzdem ein Zugriff über Indizes möglich ist. Sie erlaubt es außerdem, beliebige Objekte darin
abzuspeichern.

Attribute

Modifier Typ Name Kurzbeschreibung


protected ArrayList liste Collection-Klasse in der die
VisualNode-Objekte gespeichert
werden.

Konstruktor
- VisualNode()

innerhalb des Konstruktors wird eine neue ArrayList angelegt.

Methoden

- addNode

public void addNode(VisualNode node, int index)


public void addNode( int index, char codeLetter, int weight, String code, float xPositionNormal,
float yPositionNormal, int leftChild int rightChild, int parent)

Fügt bzw. erstellt ein VisualNode-Objekt an der mit index angegebenen Stelle ein. Ist kein
Objekt übergeben worden, so wird es aus den übergebenen Parametern erstellt.

- appendNode

public void appendNode(VisualNode node)


public void appendNode(char codeLetter, int weight, String code, float
xPositionNormal,float yPositionNormal, int leftChild, int rightChild, int parent)

Hängt bzw. erstellt ein VisualNode-Objekt an die ArrayList liste an. Ist kein Objekt übergeben
worden, so wird es aus den Parametern erstellt.

- containsNode

public int containsNode( char codeLetter)

Überprüft ob ein VisualNode-Objekt mit dem Zeichen codeLetter schon enthalten ist. Die
Methode liefert –1 zurück, wenn es noch kein O bjekt in liste gibt, welches das Zeichen
codeLetter repräsentiert. Ansonten wird der Index des Objekts in liste zurückgegeben.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 25


Huffman Code Applet 03.05.01

- removeNode

public VisualNode removeNode(int index)

Nimmt das VisualNode-Objekt an der Stelle index in liste aus der ArrayList und gibt es zurück.
Die möglichen Verweise auf diese Objekt werden nicht korrigiert!

- getNode

public VisualNode getNode(int index)

Gibt eine Kopie des VisualNode-Objekts zurück, welches sich an der Stelle index in liste
befindet.

- exchangeNodes

public boolean exchangeNodes(int index1, int index2)

Vertauscht die beiden Knoten, welche durch index1 und index2 in liste addressiert werden. Da
dieser Positionstausch Auswirkungen auf die Hierarchie hat, müssen die Verweise auf diese
Objekte neu angepaßt werden. Dabei müssen nur die beiden Kinder des Knotens
berücksichtigt werden. Es wird true zurückgegeben, wenn Methode erfolgreich ausgeführt
wurde.

- existsNode

public boolean existsNode(int index)

Gibt true zurück, wenn an der Stelle index in liste ein Knoten existiert.

- getLast

public int getLast()

Gibt den Index des letzten Elements in liste zurück. Ist liste leer, dann ist der Rückgabewert –1.

- printList

public void printList()

Gibt eine Liste aller in liste enthaltenden VisualNode-Objekte auf stdout aus.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 26


Huffman Code Applet 03.05.01

Klasse Controller

Inhalt
Die Controller-Klasse definiert das Objekt, welches die Rolle der Vermittlung zwischen dem
HuffmanCodec-Objekt und dem Applet mit der GUI übernimmt. Dabei interpretiert der Controller
die Datenstruktur, die er vom HuffmanCodec durch die Schnittstelle VisualTree und VisualNode
erhält und übergibt sie der GUI. Die eigentliche Ereignisbehandlung bleibt jedoch im Applet.
Controller-Objekte werden von dem Applet angelegt und erhalten dabei den zu kodierenden Text.
Der Controller selbst instanziert ein HuffmanCodec-Objekt, welches den zu kodierenden Text
erhält. Der HuffmanCodec gibt die Kodierung in Form des VisualTrees zurück, dieser wird dann
vom Controller ausgewertet. Um die Knoten direkt zeichnen zu können, besitzt der Controller eine
Referenz auf das TreePanel des Applets.
Die Daten für die Legende werden ebenfalls durch den Controller erstellt, hierzu dient das Attribut
legend vom Typ Zeichen[]. Treten Fehler innerhalb des Controllers auf, so werden sie durch
Exception-Handling an das Applet weitergegeben.

Attribute

Modifier Typ Name Kurzbeschreibung


private VisualTree tree Referenz auf den aktuellen
VisualTree, welche von
HuffmanCodec zurückgegeben
wird.
private TreePanel pTreePanel Referenz auf das TreePanel des
Applets. Dadurch ist es möglich
vom Controller aus direkt zu
zeichnen.
private int indexVisualTree Index der aktuellen Position im
VisualTree tree. Gibt an welche
Knoten schon gezeichnet worden
sind.
private int nOfLetters Länge vom String plainText
private String plainText Zu kodierender Eingabetext, der
vom Applet übergeben und an
HuffmanCodec weitergereicht wird.
private Zeichen[] legend Array von Objekten des Typs
Zeichen. Diese enthalten die Daten
für die Legende des Applets.
private final Color drawColor Farbe mit der auf TreePanel
gezeichnet wird. Konstante
private final Color delColor Hintergrundfarbe des TreePanels.
Wird zum Löschen einzelner Knoten
benötigt. Konstante

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 27


Huffman Code Applet 03.05.01

Konstruktor
- Controller(TreePanel p, String plainText) throws NotEnoughLettersException

TreePanel p ist eine Referenz auf das TreePanel des Applets und wird für die Methoden
drawNext(), drawAll() und drawLast() benötigt. String plainText ist der Eingabestring, der kodiert
werden soll. Innerhalb des Konstruktors wird eine Instanz von HuffmanCodec angelegt,
wodurch der Huffmanbaum erzeugt wird. Dieser wird dann durch tree referenziert.
Weiterhin wird der Eingabestring auf Korrektheit überprüft. Ist dieser kürzer als 2 Zeichen so
wird die NotEnoughLettersException geworfen. Dies geschieht ebenfalls, wenn der
Huffmanbaum nur einen Knoten enthält. Das ist der Fall, wenn der Eingabestring nur eine
Folge des selben Zeichens ist.

Methoden

- drawNext

public boolean drawNext()

Zeichnet zwei Knoten und den dazugehörenden Vaterknoten. Der Rückgabewert ist true, wenn
der letzte Knoten (Root) gezeichnet worden ist. Die schon gezeichnet Knoten erkennt man an
dem Wert indexVisualTree, der ein Index auf den VisualTree tree ist. Das Zeichnen der Knoten
und der Verbindungslinie geschieht durch aufrufen der Methoden drawNode und drawLine der
Klasse TreePanel.

- drawAll

public void drawAll()

Zeichnet den kompletten Baum durch ständiges Aufrufen der Methode drawNext bis der
Rückgabewert true ist.

- drawLast

public boolean drawLast()

Selbe Funktionsweise wie drawNext, nur in umgekehrter Richtung. Das Löschen der einzelnen
Knoten geschieht durch Überschreiben mit der Hintergrundfarbe.

- clearTree

public void clearTree()

Löscht bzw. setzt den Baum zurück. Da das Löschen den Panels vom Applet übernommen wird,
muß hier lediglich der Wert indexVisualTree auf 0 gesetzt werden.

- getProbability

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 28


Huffman Code Applet 03.05.01

private String getProbability(VisualNode node)

Berechnet die Wahrscheinlichkeit eines Zeichens mit der Formel Wahrscheinlichkeit =


Häufigkeit/ Anzahl Zeichen. Es wird das Zeichen genommen, welches durch den Knoten node
repräsentiert wird. Die Häufigkeit entspricht dem Wert von weight des Knoten. Der
Rückgabewert ist ein String, der nach 2 Stellen hinter dem Komma abgeschnitten wird.

- getCipherBit

private String getCipherBit(VisualNode node)

Ermittelt den Bitwert, der an die Verbindungslinie zum Vaterknoten gehört. Es ist das letzte
Zeichen des Strings code von node.

- getCompressionDegree

public float getCompressionDegree()

Berechnet die Kompression des Eingabetextes durch die Huffmankodierung. Jedes Zeichen des
Eingabestrings wird dazu mit 8 Bit (ASCII-Kodierung) angesetzt. Die Kompression wird anhand
folgender Formel berechnet:
(Anzahl ASCIIBits – Anzahl HuffmanBits)/ Anzahl ASCIIBits = Kompression
Es wird auf 2 Stellen hinter dem Komma gerundet.

- buildLegend

private Zeichen[] buildLegend()

Erzeugt eine Tabelle in der alle Zeichen mit ihrer Wahrscheinlichkeit und ihrer Kodierung
abgelegt sind. Für jedes Zeichen wird ein O bjekt Zeichen angelegt, welches in Zeichen[]
gespeichert wird. Da nur Blätter ein echtes Zeichen repräsentieren, wird nur für jedes Blatt ein
Objekt von Zeichen angelegt.

- getLegend

public Zeichen[] getLegend()

Gibt ein Array von Zeichenobjekten zurück, welche die Daten für die Legende des Applets
enthalten. Zum Erstellen der Legende wird die Methode buildLegend() aufgerufen, deren
Ergebnis in dem Attribut legend abgespeichert werden.

- getCipherText

public String getCipherText()

Erzeugt einen String in dem jedes Zeichen des Eingabestrings durch seine Huffmankodierung
ersetzt wird. Zum schnelleren Zugriff auf die Kodierung werden die Daten aus legend gelesen.
Intern wird ein StringBuffer als Zwischenspeicher benutzt.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 29


Huffman Code Applet 03.05.01

Klasse Zeichen

Inhalt
Die Legende des Applets listet alle Zeichen auf, um so dem Benutzer einen Überblick über den
Baum zu verschaffen. Zu jedem Zeichen werden noch die zusätzlichen Eigenschaften des
Wahrscheinlichkeit und Huffman- Kode angezeigt. Da in der Tabelle nur die echten Zeichen
aufgelistet werden sollen, werden Zeichenobjekte nur für jedes Blatt angelegt. Sie bilden die
Schnittstelle zwischen dem Controller und dem Applet und übergeben die Informationen die für die
Legende benötigt werden. Dies geschieht in einem eindimensionalem Array von Zeichen.

Attribute
Modifier Typ Name Kurzbeschreibung
private float fProbability Wahrscheinlichkeit des Zeichens,
gerundet auf 2 Stellen hinter dem
Komma.
private String szBitCode Huffmankodierung des Zeichens
private char cCodeLetter Zeichen an sich.

Konstruktor
- Zeichen()

Standardkonstruktor, muß explizit angelegt werden, da auch ein zweiter Konstruktor vorhanden
ist.

- public Zeichen(char z, float p, String sz)

Konstruktor legt Zeichen z mit Wahrscheinlichkeit p und dem Huffman-Kode sz an.

Methoden
Zu jedem Attribut gibt es die üblichen get- und set- Methoden.

- set

public void set(char z, float p, String sz)

Setzt alle Attribute auf die Werte der übergebenen Parameter.

- toString

public String toString()

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 30


Huffman Code Applet 03.05.01

Gibt die Werte der Attribute als String zurück. Dient vor allem zum Debuggen.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 31


Huffman Code Applet 03.05.01

Klasse NotEnoughLettersException

Inhalt
Die Klasse NotEnoughLettersException erbt von der Klasse Exception des JFC. Diese Exception wird
vom Controller geworfen, wenn der Eingabestring weniger als 2 Zeichen enthält, oder eine Folge
des gleichen Zeichens ist.

Konstruktor
- NotEnoughLettersException()

Ruft den Konstuktor der Vaterklasse auf.

- NotEnoughLettersException(String s)

Ruft den Konstuktor der Vaterklasse mit dem String s auf.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 32


Huffman Code Applet 03.05.01

Klasse huffman

Inhalt
Die Klasse huffman ist von der Klasse Applet aus der Java API abgeleitet. Sie beinhaltet die
Initalisierung sämtlicher grafischer Objekte im Appletfenster. Die Klasse beinhaltet zusätzlich eine
„main“ Funktion die es ermöglicht, das Applet mit der Java-Virtual-Machine direkt zu starten.
Die Klasse verwendet den Layout Manager GridBagLayout (aus der Java API) sowie die
vorkompilierte Klasse GridBagConstraints2 welche die Parameter bezüglich der Anordnung der
einzelnen grafischen Objekte einstellt.
Button-Events wie z.b. drawTree oder drawNext werden von der Klasse abgefangen und bearbeitet
bzw. weitergereicht an die Controller Klasse.

Attribute
Modifier Typ Name Kurzbeschreibung
Public Controller con Beinhaltet den aktuellen Controller
der für das Errechnen der
Koordinaten zuständig ist.
Public TreePanel P1 Enthält das TreePanel-Objekt das
den Code Baum anzeigt.
Public Jpanel jp Ist die gecastete Version des
TreePanels P1. Der Designer des
JDeveloper erwartet ein Objekt
dieses Typs anstatt des Typs
TreePanel.
Public Label Label1 Alle Label Variablen wurden
automatisch vom Designer des
Jdevelopers erstellt und dienen nur
der Anzeige von konstantem Text
auf dem Applet.
Public boolean isStandAlone Wurde von Jdeveloper bei der
Erstellung der Applet Klasse
generiert und dient dazu das das
Program auch mit der Java VM per
main() Methode aufgerufen werden
kann.
Public ScrollBar ScrollbarV,Scrollbar Dienen der Darstellung der
H Scrollbar zum scrollen des Code
Baums
Public JtextField Plaintext Das grafische Objekt zum Eingeben
des Klartextes.
Public String Header Enthält den Tabellenkopf für die
Legende.

Public DefaultTableMode Model Überschreibt DefaultTableModel um

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 33


Huffman Code Applet 03.05.01

l die Legendezellen nicht editierbar zu


machen.
Public Jtable Legend Grafisches O bjekt zum Darstellen
der Legende
Public Button Lastbutton,nextbutto Grafische Objekte zum Darstellen
n der einzelnen Buttons
Public TextArea CypherText TextFeld zum Darstellen des
Schlüsseltextes
Public JscrollPane LegendJSP Dieses ScrollPane O bjekt dient dem
Scrollen der Legende falls die
Anzahl der Zeilen darin zu gross
wird.
protected GridBagLayout GridbagLayout1 Definiert das die grafischen Objekte
des Applets im GridBagLayout
geschehen soll, wurde vom
JDeveloper automtisch generiert.

Konstruktor
- huffman()

hat keine Aufgabe

Methoden
Init()

Initialisiert das Applet indem es jbInit() aufruft.

jbInit()

vom Designer des JDeveloper generierte Funktion, die die Anzeige und Positionierung der
grafischen Objekte des Applets vornimmt. Es werden ausserdem für die verschiedenen Buttons
ActionListener installiert, die auf Klicken der Buttons reagieren und diese Events dann an
entsprechende Funktionen weiterleiten.

componentResized(ComponentEvent e)

wird aufgerufen wenn sich die Größe des Applets ändert. Wenn das Applet sich in der Größe
verändert müssen die Scrollbars angepasst werden da sich auch die Größe des Feldes für die
Anzeige des Code Baumes ändert.

AdjustmentValuechanged(AdjustmentEvent e)

Wird aufgerufen wenn der Code Baum gescrollt wird. Passt die neuen Xund Y Koordinaten des
Code Baumes an.

Start()
Stop()
Destroy()

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 34


Huffman Code Applet 03.05.01

Funktionen die vom JDeveloper bei Erstellung der Applet Klasse eingefügt wurden.

DrawLegend

Zeichnet die Legende(Zeichen, Wahrscheinlichkeit und BitString) für alle Zeichen des Baumes

clear_actionPerformed(ActionEvent e)
tree_actionPerformed(ActionEvent e)
next_actionPerformed(ActionEvent e)
previous_actionPerformed(ActionEvent e)

Diese Event-Funktionen werden aufgerufen sobald der entsprechende Button gedrückt wurde.
Falls noch kein Controller Objekt existiert (z.b. ein neuer Text eingegeben wurde) wird dieses
von der Funktion zunächst erstellt. Das Controller Objekt bekommt dabei das TreePanel
Objekt „p1“ übergeben um deren Funktionen zum Zeichnen der Knoten aufrufen zu können.
Die Funktion ruft nun die dem Button zugeordenete Funktion des Controllers auf(drawNext,
drawPrevois...), und holt sich vom Controller noch die Informationen zur Legende und dem
Kompressionsgrad, die es dann anzeigt.

main(String[] args)

Wird nur aufgerufen das Program wenn nicht als Applet sondern durch „java huffman“
aufgerufen wurde. Initialisiert ein Fenster und erzeugt dann ein Objekt des Applets in diesem
Fenster.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 35


Huffman Code Applet 03.05.01

Klasse UpperCaseField

Inhalt
Diese Klasse ist von JTextField abgeleitet und stellt das grafische Objekt für die Eingabe der
Zeichenfolge dar. Die Klasse begrenzt dieses Feld auf eine feste Länge.

Attribute
keine

Konstruktor
huffman()

hat keine Aufgabe

createDefaultModel()

verhindert das Eingeben von mehr als 30 Zeichen

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 36


Huffman Code Applet 03.05.01

Klasse TreePanel

Inhalt
Diese Klasse ist von JPanel abgeleitet und beschreibt das Feld zum Anzeigen des Code Baumes.
Die Klasse stellt Funktionen zum Zeichnen der Knoten und Linien bereit. Die Eingabekoordinaten
für diese Funktionen sind normiert und liegen zwischen 0.0 und 1.0 und werden von der Klasse auf
die richtige Größe umgerechnet. Alle Knoten und Linien werden erst in einen Puffer gezeichnet und
nur der sichtbare Bereich des Baumes wird dann auf dem Bildschirm ausgegeben. Wenn der Baum
nicht in das Anzeigefeld passt kann gescrollt werden. Der normalisierte Radius (auch zwischen 0.0
und 1.0) bestimmt den Zoomfaktor für die Umrechnung der Koordinaten indem immer auf einen
konstanten Radius von 15 Pixeln gezoomt wird.

Attribute

Modifier Typ Name Kurzbeschreibung


Public Int Width,Height Definiert die Breite und Höhe des
Puffers und damit des
Pixelkoordinatensystems in Pixeln
Public int Radius= 15 Definiert einen konstanten Radius
von 15 Pixeln. Diese Wert ist
Bezugsgröße und wird beim
Zoomen von normalisierten auf
Pixel Koordinaten verwendet.
Public BufferedImage O ffScreenImage Enthält den Inhalt des ganzen
CodeBaumes. Es kann aber immer
nur ein Teil dieses Puffers angezeigt
werden.
Public Graphics2D O ffScreenContext Alle verwendeten Funktionen der
Java API benötigen zum Zeichnen
von Linien und Kreisen dieses
Objekt.
Public Int X,Y Definiert die Koordinaten der Stelle
im Puffer die den sichtbaren Teil des
Baumes darstellen. Ändert sich beim
Scrollen.

Konstruktor
- TreePanel()

setzt einen „Standard“-normalisierten Radius am Anfang

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 37


Huffman Code Applet 03.05.01

Methoden

paint(Graphics g)

zeichnet den sichtbaren Bereich des offScreenImage auf den Bildschirm

setRadius(float r)

bestimmt den Zoomfaktor (den Faktor mit dem die normalisierten Koordinaten multipliziert
werden müssen um Pixel-Koordinaten zu bekommen). Erzeugt ein virtuelles Bild
(offScreenImage) mit der Größe der maximalen Pixelkoordinaten und löst das Event
COMPONENT_RESIZED aus, damit die ScrollBars sich dem neuen Zoom anpassen.

drawNode(float fx,float fy,String Mitte,String text,Color col)

zeichnet einen Knoten mit Bezeichnung in das virtuelle Bild

drawLine(float fx,float fy,float fxx,float fyy,Color col, String zahl)

zeichnet eine Linie zwischen 2 virtuellen Koordinaten

clearImage()

löscht den ganzen Puffer.

int getRealX(float x)
int getRealY(float y)

wandelt normalisierte Koordinaten in Koordinaten um, die im Puffer (gesamter Zeichenraum


für den Baum) gültig sind.

Stefan Schmitz, Ma tthia s Kloss, Ma tthia s Wita ßek 38