Huffman coding is a lossless data compression algorithm that assigns variable-length codes to input symbols based on their frequencies of occurrence. Developed by David A. Huffman in 1952 while he was a PhD student at MIT, the algorithm produces a prefix-free code (no code word is a prefix of another) that minimizes the expected code length for a given set of symbol probabilities. It is a fundamental technique in information theory, often used as a building block in more complex compression schemes, and its efficiency stems from its construction via a binary tree (the Huffman tree). The method is optimal among symbol-by-symbol coding schemes when the symbol probabilities are known and independent.
1 History
1.1 David Huffman's original paper
David A. Huffman developed the algorithm in 1952 as a term paper for Robert Fano's information theory class at MIT. Instead of writing a traditional survey, Huffman devised a new method for constructing optimal prefix codes. His paper, "A Method for the Construction of Minimum-Redundancy Codes," was published in the *Proceedings of the IRE* (now IEEE) in September 1952. The algorithm solved a problem that had been studied by Claude Shannon and Fano, who had produced near-optimal but not always optimal codes.
1.2 Subsequent developments
Following the original paper, Huffman coding became a cornerstone of data compression. In the 1970s and 1980s, its integration into file compression utilities such as PKZIP and later GZIP made it widely used. Researchers also developed adaptive variants that update the code tree dynamically without requiring a priori probability knowledge. The algorithm's optimality for symbol-by-symbol coding was proven formally, and it became a standard topic in textbooks on information theory and algorithms.
2 Algorithm
2.1 Construction of the Huffman tree
The algorithm builds a binary tree from the bottom up by repeatedly merging the two least frequent symbols. The tree leaves correspond to input symbols, and the path from the root to each leaf defines its code.
2.1.1 Building the frequency table
The first step is to compute the frequency (or probability) of each symbol in the input data. For example, in a text file, one counts the occurrence of each character. These frequencies serve as the initial weights for the leaf nodes.
2.1.2 Merging minimum-frequency nodes
A priority queue (typically a min‑heap) is used to store all nodes, each with a frequency weight. The algorithm repeatedly extracts the two nodes with the smallest frequencies, creates a new internal node whose weight is the sum of the two, and inserts that internal node back into the queue. This process continues until only one node remains – the root of the Huffman tree.
2.1.3 Assigning codes (0/1 convention)
Once the tree is built, each left edge is conventionally labeled 0 and each right edge labeled 1 (or vice versa, as long as the assignment is consistent). The code word for a symbol is obtained by traversing from the root to its leaf, concatenating the bits encountered. Because the tree is a full binary tree (every internal node has exactly two children), the resulting code is prefix‑free.
2.2 Example with a simple alphabet
Consider an alphabet consisting of five symbols with frequencies: A (45), B (13), C (12), D (16), E (9). The Huffman tree construction proceeds as follows:
- Initial leaves: [E(9), C(12), B(13), D(16), A(45)]
- Merge E(9) and C(12) → internal node (21)
- Merge B(13) and D(16) → internal node (29)
- Merge (21) and (29) → internal node (50)
- Merge (50) and A(45) → root (95)
Assigning 0/1 (say left=0, right=1), the codes might be:
- A: 0
- B: 101
- C: 100
- D: 111
- E: 110
The average code length is (1×45 + 3×13 + 3×12 + 3×16 + 3×9) / 95 = 1.72 bits per symbol, which is optimal for these frequencies.
2.3 Time and space complexity
Using a priority queue, the Huffman tree can be constructed in O(n log n) time for n distinct symbols. If frequencies are presorted, the process can be reduced to O(n). The space complexity is O(n) for storing the tree nodes and code assignments. In practice, the dominant cost is often the scanning of input data to build the frequency table.
3 Properties
3.1 Optimality
Huffman coding is optimal in the sense that, among all prefix codes that encode each symbol separately, it minimizes the expected code length for a given set of symbol probabilities.
3.1.1 Proof of optimality for given probabilities
The proof typically proceeds by induction on the number of symbols. For two symbols, the optimal code is trivially 0 and 1. Assuming the algorithm is optimal for n‑1 symbols, one shows that merging the two least probable symbols yields a tree that can be transformed into any optimal tree for n symbols without increasing the expected length. The greedy merging therefore preserves optimality.
3.1.2 Prefix-free condition
Huffman codes are prefix‑free by construction because each symbol corresponds to a leaf in the tree, and no codeword is a prefix of another (that would correspond to an internal node being used as a code). This property ensures that decoding can be performed unambiguously as a stream of bits is traversed.
3.2 Expected code length
The expected number of bits per symbol, denoted L, is the sum over all symbols of (frequency × code length). Huffman coding achieves the minimum possible L among symbol‑by‑symbol prefix codes.
3.2.1 Relationship to entropy
The entropy H of the source, defined as H = ‑Σ p_i log₂ p_i, provides a lower bound on any uniquely decodable code. Huffman coding attains an average length L that satisfies H ≤ L < H + 1. When all probabilities are powers of ½, L = H exactly; otherwise, the code may waste up to one bit per symbol due to the integer‑length constraint.
3.3 Limitations
3.3.1 Fixed symbol sizes
Huffman coding treats each symbol as an atomic unit. In many applications, symbols are bytes (8 bits). The algorithm cannot exploit correlations between symbols, and its performance degrades when symbol probabilities are not well matched to powers of ½.
3.3.2 Minimum variance concerns
The standard Huffman algorithm minimizes the expected code length but not the variance of the code lengths. Variations of the algorithm can be designed to reduce the spread of code lengths while preserving optimality, which is useful when transmission or storage requires a stable bitrate.
4 Variations
4.1 Adaptive Huffman coding
Adaptive Huffman coding, also known as dynamic Huffman coding, builds the frequency tree incrementally as data are processed, eliminating the need for a separate pass to compute statistics. This is useful for streaming applications.
4.1.1 Dynamic tree updating
The algorithm maintains the Huffman tree and updates it after each symbol is encoded or decoded. The update may involve rearranging nodes to preserve the prefix‑free property and the sibling property (nodes are ordered by weight). The most common implementation is the FGK (Faller–Gallager–Knuth) algorithm, later improved by Vitter.
4.2 n-ary Huffman coding
The basic Huffman algorithm can be generalized to an n‑ary tree, where each internal node has up to n children. Instead of merging two smallest frequencies, the algorithm merges n smallest frequencies at each step, possibly adding dummy symbols with zero frequency to ensure a full tree. This variant is used when the output alphabet has more than two symbols, such as in ternary or octal codes.
4.3 Huffman coding with unequal symbol costs
In some contexts, the cost of transmitting a 0 and a 1 may differ (e.g., in run‑length limited channels). Modified Huffman algorithms can assign variable‑length codes where the edges have different weights, optimizing the expected cost rather than the number of bits.
4.4 Canonical Huffman codes
Canonical Huffman codes enforce a particular ordering of the codewords (usually by length and then by lexical order) to simplify decoding. They are widely used because the decoder only needs the code lengths for each symbol, not the full tree structure.
4.4.1 Efficient decoding table construction
Given a list of symbols and their canonical code lengths, a lookup table can be built in linear time. The decoder reads bits and uses the table to map bit sequences directly to symbols, often with fast branch‑free implementations.
5 Applications
5.1 File compression (e.g., ZIP, GZIP)
Huffman coding is a key component in many file compression tools. It appears as the entropy coding stage after a dictionary‑based transform.
5.1.1 Combination with LZ77 (DEFLATE)
The DEFLATE algorithm, used in ZIP and GZIP formats, combines LZ77 (a sliding‑window dictionary matching scheme) with Huffman coding. LZ77 reduces redundancy by replacing repeated sequences with references, and the resulting literals and lengths/distances are then Huffman‑coded. DEFLATE also uses separate Huffman trees for literals/lengths and distances, and optionally encodes the tree description itself.
5.2 Image compression (e.g., JPEG)
In JPEG, Huffman coding is used as the entropy encoding step after the discrete cosine transform and quantization. The quantized DCT coefficients are run‑length encoded, and the runs are Huffman‑coded according to tables specified in the JPEG standard. Baseline JPEG uses two separate Huffman tables (DC and AC coefficients) per component.
5.3 Multimedia codecs (e.g., MP3)
MP3 audio compression employs Huffman coding to encode the quantized frequency subband samples. The Huffman tables in MP3 are predefined and optimized for typical audio distributions. Although more modern codecs like AAC use arithmetic coding, Huffman coding remains in many legacy and embedded systems.
5.4 Text compression and entropy coding
Huffman coding is frequently used for compressing text files, either directly or as part of a pipeline. Many Unix utilities (e.g., compress, bzip2's initial stage) incorporate Huffman codes. It is also a pedagogical tool for demonstrating the principle of entropy encoding.
6 Related concepts
6.1 Shannon–Fano coding
Shannon–Fano coding is a predecessor of Huffman coding developed by Claude Shannon and Robert Fano. It also produces prefix codes by recursively splitting a set of symbols into subsets with roughly equal total probabilities. Unlike Huffman codes, Shannon–Fano codes are not guaranteed to be optimal; they can have an expected length greater than the minimum by up to one bit.
6.2 Arithmetic coding
Arithmetic coding maps the entire input sequence to a single fractional number between 0 and 1, rather than assigning fixed codes to individual symbols. It can achieve an average code length arbitrarily close to the entropy, even for large alphabets. However, it is more computationally intensive and was historically encumbered by patents.
6.3 Comparison with Huffman coding
Huffman coding is simpler to implement and requires only integer arithmetic, while arithmetic coding can achieve better compression, especially for skewed probabilities (e.g., binary sources with one dominant symbol). Huffman codes have an overhead of at most one bit per symbol, whereas arithmetic codes can approach the entropy bound asymptotically. For many practical applications, the difference is small, and Huffman coding remains widely used due to its speed and ease of implementation.
7 See also
- Data compression
- Entropy encoding
- Prefix code
- Golomb coding
- Universal code (data compression)