Huffman-Codierung einfach erklärt
Die Huffman-Codierung ist ein verlustfreies Kompressionsverfahren: Häufige Zeichen erhalten kurze, seltene Zeichen längere Bitfolgen. Ein präfixfreier Code sorgt dafür, dass du die codierten Daten eindeutig und ohne Trennzeichen decodieren kannst.
Hake ab, was du schon kannst — und komm am Ende hierher zurück!
Warum Präfixfreiheit wichtig ist
Bei einem Code mit fester Länge besitzt jedes Zeichen gleich viele Bits. Die Grenzen zwischen den Codewörtern sind dadurch klar. Für fünf verschiedene Zeichen werden mindestens drei Bits pro Zeichen benötigt.
Variable Codewortlängen können Speicherplatz sparen. Sie müssen aber so gewählt werden, dass beim Lesen keine Mehrdeutigkeit entsteht.
Präfixfreiheit
Ein Code ist präfixfrei, wenn kein Codewort den Anfang eines anderen Codewortes bildet. Diese Eigenschaft wird auch Fano-Bedingung genannt.
Das Gegenbeispiel a→0, b→01, c→1 ist nicht präfixfrei: 0 ist der Anfang von 01. Deshalb kann 01 sowohl als b als auch als ac gelesen werden.
Der Code a→0, b→10, c→11 ist dagegen präfixfrei. Nach 0 steht sofort a fest; nach einer führenden 1 entscheidet das nächste Bit zwischen b und c.
Unterschiedliche Codewortlängen sind nicht das Problem. Entscheidend ist, dass kein vollständiges Codewort am Anfang eines anderen steht.
So baust du den Huffman-Baum
Ausgangspunkt sind die absoluten Häufigkeiten der Zeichen. Jedes Zeichen beginnt als Blatt mit seinem Gewicht.
Der binäre Huffman-Algorithmus arbeitet anschließend von unten nach oben:
- Wähle die beiden Wurzeln mit den kleinsten Gewichten.
- Verbinde sie unter einem neuen Knoten.
- Addiere ihre Gewichte und schreibe die Summe an den neuen Knoten.
- Ordne den neuen Teilbaum wieder bei den übrigen Knoten ein.
- Wiederhole das Verfahren, bis nur noch eine Wurzel übrig ist.
- Beschrifte an jedem Knoten eine Kante mit
0und die andere mit1.
Weil der Algorithmus in jedem Schritt die aktuell kleinsten Gewichte auswählt, ist er ein Greedy-Algorithmus.
Für abrakadabra gelten die Häufigkeiten a:5, b:2, r:2, k:1 und d:1.
Eine mögliche Folge der Zusammenfassungen lautet:
k:1undd:1ergeben einen Teilbaum mit Gewicht2.- Dieser Teilbaum und
r:2ergeben Gewicht4. b:2und der Teilbaum mit Gewicht4ergeben Gewicht6.a:5und der Teilbaum mit Gewicht6ergeben die Wurzel mit Gewicht11.
Ein passendes Codebuch ist:
| Zeichen | Häufigkeit | Codewort | Länge |
|---|---|---|---|
a | 5 | 0 | 1 |
b | 2 | 10 | 2 |
r | 2 | 110 | 3 |
k | 1 | 1110 | 4 |
d | 1 | 1111 | 4 |
Du liest jedes Codewort als Pfad von der Wurzel zum Blatt ab.
Bei gleichen Gewichten darfst du zwischen mehreren Knoten wählen. Dadurch können andere Bäume und Codewörter entstehen. Sie bleiben korrekt, wenn die Konstruktion vollständig durchgeführt wird und die Kanten an jedem Knoten eindeutig mit 0 und 1 beschriftet sind.
Wähle in jeder Lücke die passende Form und prüfe anschließend deine Antworten.
Zuerst werden die Gewichte verbunden. Der neue Knoten erhält ihre . Das Verfahren endet an der . Ein Codewort führt von der Wurzel zu einem .
So codierst und decodierst du
Beim Codieren ersetzt du jedes Zeichen der Reihe nach durch sein Codewort. Du benötigst dafür das fertige Codebuch.
Mit dem Codebuch aus dem vorherigen Kapitel wird abrakadabra so zerlegt:
a | b | r | a | k | a | d | a | b | r | a
0 | 10 | 110 | 0 | 1110 | 0 | 1111 | 0 | 10 | 110 | 0
Ohne Zwischenräume entsteht:
01011001110011110101100
Die Bitfolge umfasst 23 Bit.
Zum Decodieren brauchst du denselben Baum oder dasselbe Codebuch:
- Starte an der Wurzel.
- Folge für jedes Bit der Kante mit derselben Beschriftung.
- Gib beim Erreichen eines Blattes das zugehörige Zeichen aus.
- Starte für das nächste Bit wieder an der Wurzel.
Im Beispiel zerfällt der Anfang 010110 eindeutig in 0 | 10 | 110. Das ergibt a | b | r.
Beim Decodieren endet ein Zeichen genau dann, wenn du ein Blatt erreichst. Zusätzliche Trennzeichen sind wegen der Präfixfreiheit nicht nötig.
So beurteilst du die Speicherwirkung
Die Länge eines codierten Textes erhältst du, indem du für jedes Zeichen seine Häufigkeit mit seiner Codewortlänge multiplizierst und alle Produkte addierst.
Für abrakadabra gilt:
$$B = 5 \cdot 1 + 2 \cdot 2 + 2 \cdot 3 + 1 \cdot 4 + 1 \cdot 4 = 23$$
Der Huffman-Code benötigt für den eigentlichen codierten Text also 23 Bit.
Ein fester Code braucht bei fünf verschiedenen Zeichen drei Bits pro Zeichen. Für die elf Zeichen wären das:
$$11 \cdot 3 = 33\text{ Bit}$$
Beim codierten Text werden somit 10 Bit eingespart. Die mittlere Codewortlänge beträgt:
$$\bar l = \frac{23}{11} \approx 2{,}09\text{ Bit pro Zeichen}$$
Dieser Vergleich betrachtet zunächst nur die codierte Nachricht. Für eine vollständige Übertragung muss der Empfänger auch den Baum oder das Codebuch kennen. Dessen Speicherbedarf kann die Einsparung bei kurzen Nachrichten aufheben.
Wann Huffman optimal ist und wann nicht
Huffman minimiert die gewichtete mittlere Codewortlänge unter den betrachteten symbolweisen Präfixcodes, wenn die Symbolhäufigkeiten bekannt sind. Diese Aussage bedeutet nicht, dass Huffman jedes andere denkbare Kompressionsverfahren übertrifft.
Die Greedy-Entscheidung ist hier erfolgreich: Die beiden seltensten Symbole dürfen in einem optimalen Baum besonders tief als Geschwister liegen. Nach ihrem Zusammenfassen entsteht dasselbe Optimierungsproblem mit einem Symbol weniger. Durch diese wiederholte Reduktion entsteht ein optimaler Präfixbaum.
Trotzdem wird nicht jede Datei insgesamt kleiner:
- Sind die Zeichen fast gleich häufig, unterscheiden sich die Codewortlängen nur wenig.
- Bei kurzen Daten kann das zusätzlich benötigte Codebuch mehr Platz beanspruchen als eingespart wird.
- Ein statischer Huffman-Code passt zu den Häufigkeiten, aus denen er konstruiert wurde. Bei einer stark anderen Verteilung kann er ungeeignet sein.
- Verfahren, die ganze Zeichenfolgen oder andere Datenmuster ausnutzen, betrachten ein anderes Optimierungsproblem.
Zwei korrekte Huffman-Bäume können bei Gleichständen verschiedene Codewörter liefern. Für abrakadabra sind dennoch Codierungen mit insgesamt 23 Bit möglich. Entscheidend ist die gewichtete Gesamtlänge, nicht die konkrete Wahl von 0 und 1 an einer Verzweigung.
Karteikasten
Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.
Alles auf einen Blick
- Huffman-Codierung
- Grundlage: Symbolhäufigkeiten
- Konstruktion: zwei kleinste Gewichte verbinden
- Ergebnis: binärer Präfixbaum
- Codieren: Zeichen durch Wurzel-Blatt-Pfade ersetzen
- Decodieren: Bits bis zum nächsten Blatt verfolgen
- Bewertung: gewichtete Bitlänge plus Codebuchaufwand
- Grenze: optimal nur im betrachteten Bereich der Präfixcodes
Mit Google fortfahren