Huffman-Codierung einfach erklärt

Huffman-Codierung einfach erklärt
Huffman-Codierung einfach erklärt
Für Quiz, Lückentext, Lernkarten und Fortschritt ist JavaScript nötig. Alle Inhalte und Lösungen bleiben direkt lesbar.

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.

Deine Lernziele

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.

Definition

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.

Merke

Unterschiedliche Codewortlängen sind nicht das Problem. Entscheidend ist, dass kein vollständiges Codewort am Anfang eines anderen steht.

Teste dich
Frage 1 von 1LeichtWelche Codewortmenge ist präfixfrei?
Lösung: 0, 10, 11 — Prüfe jedes Codewort: Es darf nicht den vollständigen Anfang eines längeren Codewortes bilden.
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:

  1. Wähle die beiden Wurzeln mit den kleinsten Gewichten.
  2. Verbinde sie unter einem neuen Knoten.
  3. Addiere ihre Gewichte und schreibe die Summe an den neuen Knoten.
  4. Ordne den neuen Teilbaum wieder bei den übrigen Knoten ein.
  5. Wiederhole das Verfahren, bis nur noch eine Wurzel übrig ist.
  6. Beschrifte an jedem Knoten eine Kante mit 0 und die andere mit 1.

Weil der Algorithmus in jedem Schritt die aktuell kleinsten Gewichte auswählt, ist er ein Greedy-Algorithmus.

Beispiel

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:

  1. k:1 und d:1 ergeben einen Teilbaum mit Gewicht 2.
  2. Dieser Teilbaum und r:2 ergeben Gewicht 4.
  3. b:2 und der Teilbaum mit Gewicht 4 ergeben Gewicht 6.
  4. a:5 und der Teilbaum mit Gewicht 6 ergeben die Wurzel mit Gewicht 11.

Ein passendes Codebuch ist:

ZeichenHäufigkeitCodewortLänge
a501
b2102
r21103
k111104
d111114

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.

Lückentext

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 .

Lösungen: Lücke 1: zwei kleinsten; Lücke 2: Summe; Lücke 3: Wurzel; Lücke 4: Blatt. Die Konstruktion verbindet wiederholt die zwei kleinsten Gewichte. Erst der vollständige Wurzel-Blatt-Pfad ist ein Codewort.
Teste dich
Frage 1 von 1SchwerKonstruiere gedanklich einen Huffman-Baum für w:1, x:2, y:3 und z:4. Welche Codewortlängen entstehen?
Lösung: z hat Länge 1, y Länge 2 und w sowie x Länge 3. — Verbinde zuerst 1+2=3, danach die beiden Gewichte 3+3=6 und zuletzt 4+6=10. Daher liegt z in Tiefe 1, y in Tiefe 2 und w sowie x in Tiefe 3.
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.

Beispiel

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:

  1. Starte an der Wurzel.
  2. Folge für jedes Bit der Kante mit derselben Beschriftung.
  3. Gib beim Erreichen eines Blattes das zugehörige Zeichen aus.
  4. 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.

Merke

Beim Decodieren endet ein Zeichen genau dann, wenn du ein Blatt erreichst. Zusätzliche Trennzeichen sind wegen der Präfixfreiheit nicht nötig.

Teste dich
Frage 1 von 1MittelWas ergibt 010110 mit den Codes a→0, b→10, r→110?
Lösung: abr — Die eindeutige Zerlegung lautet 0 | 10 | 110, also a | b | r.
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}$$

Gut zu wissen

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.

Teste dich
Frage 1 von 1MittelWarum spart der Huffman-Code im Beispiel Bits?
Lösung: Das häufigste Zeichen a erhält das kürzeste Codewort. — Huffman bleibt verlustfrei. Die Einsparung entsteht durch unterschiedlich lange Codewörter, nicht durch das Entfernen von Zeichen.
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.
Beispiel

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.

Teste dich
Frage 1 von 1SchwerEine sehr kurze Nachricht wird durch Huffman von 33 auf 23 Datenbits verkürzt. Warum kann die vollständige Speicherung trotzdem größer werden?
Lösung: Zusätzlich müssen Informationen über den Baum oder das Codebuch gespeichert werden. — Für die Gesamtgröße zählen sowohl die codierten Daten als auch die Informationen, die zur Rekonstruktion des Codes nötig sind.
Karteikasten
Karteikasten

Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.

Alles auf einen Blick
Mindmap
  • 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
Abschluss-Check
Teste dich
Frage 1 von 3LeichtWoran erkennst du einen präfixfreien Code?
Lösung: Kein Codewort bildet den Anfang eines anderen Codewortes. — Präfixfreiheit hängt allein davon ab, ob ein vollständiges Codewort am Anfang eines anderen steht.
Frage 2 von 3MittelWelche Gewichte werden beim ersten Huffman-Schritt für a:5, b:2, r:2, k:1, d:1 verbunden?
Lösung: k:1 und d:1 — Die beiden kleinsten Gewichte sind 1 und 1; ihr neuer Vater erhält Gewicht 2.
Frage 3 von 3SchwerEine Nachricht verwendet plötzlich andere Zeichenhäufigkeiten als der vorhandene Huffman-Baum. Welche Folgerung ist richtig?
Lösung: Der Code bleibt bei korrektem Codebuch decodierbar, kann aber weniger gut komprimieren. — Ein statischer Baum behält seine Codewörter. Eine veränderte Verteilung beeinflusst deshalb die Kompressionswirkung, nicht automatisch die Eindeutigkeit.

Passend dazu