Introduction

Huffman coding builds an optimal prefix code for a set of symbols with known frequencies: no codeword is a prefix of another, so a bit stream decodes uniquely without separators, and the expected codeword length is minimised among all binary prefix codes.

The construction is a textbook greedy algorithm: repeatedly merge the two lightest trees. The same merge pattern also solves optimal merge patterns (combine nn sorted files of given lengths at minimum total cost). Both belong to the greedy part of the syllabus and reuse a binary heap as the priority queue.

Prerequisites

  • Greedy Algorithms: greedy-choice property and optimal substructure.
  • Binary Heaps: extract-min and insert in O(lg⁡n)O(\lg n).
  • Full binary trees: every node has 0 or 2 children (needed for the optimality argument).

Core concepts

Prefix codes

A code is prefix-free (a prefix code) when no codeword is a prefix of another. Equivalently, the codewords are the root-to-leaf paths of a binary tree whose leaves are the symbols (left = 0, right = 1, or the reverse). Fixed-length codes are prefix-free but usually longer than necessary when frequencies are skewed.

The cost of a tree TT for frequencies f(c)f(c) is

B(T)=∑c∈Cf(c) dT(c),B(T) = \sum_{c \in C} f(c)\, d_T(c),

where dT(c)d_T(c) is the depth of leaf cc (edge count). B(T)B(T) is the total number of bits used to encode a file whose symbol counts are the f(c)f(c) values.

Full trees only

An optimal prefix code corresponds to a full binary tree: every internal node has exactly two children. A node with one child can be bypassed, shortening every codeword in that subtree and lowering B(T)B(T).

Optimal merge patterns

Given nn sorted runs of lengths ℓ1,…,ℓn\ell_1, \ldots, \ell_n, merging two runs of lengths aa and bb costs a+ba + b. The total cost of a binary merge tree equals the sum, over every internal node, of the combined size of its two children, which is the same formula as B(T)B(T) with f(c)=ℓcf(c) = \ell_c. So Huffman’s construction also yields an optimal merge order.

Algorithms and pseudocode

Pseudocode uses 1-based arrays, <- for assignment and a min-priority queue Q of trees keyed by freq.

Text
HUFFMAN(C)
1  n <- |C|
2  Q <- C                                    // min-priority queue on freq
3  for i <- 1 to n - 1
4      allocate a new node z
5      z.left <- x <- EXTRACT-MIN(Q)
6      z.right <- y <- EXTRACT-MIN(Q)
7      z.freq <- x.freq + y.freq
8      INSERT(Q, z)
9  return EXTRACT-MIN(Q)                     // the root

Input. A set CC of n≥2n \ge 2 symbols, each with a positive frequency freq.

Output. The root of an optimal Huffman tree.

Time. With a binary heap, each of the n−1n - 1 iterations does two extract-mins and one insert: O(nlg⁡n)O(n \lg n). Building the initial heap is O(n)O(n). Space Θ(n)\Theta(n) for the tree nodes.

Counting facts. The loop runs exactly n−1n - 1 times, so the tree has nn leaves, n−1n - 1 internal nodes, 2n−12n - 1 nodes in all and 2n−22n - 2 edges. The queue sees 2(n−1)2(n-1) EXTRACT-MIN calls inside the loop (plus the final one) and n−1n - 1 INSERT calls. If the frequencies arrive already sorted, two FIFO queues (one for the original leaves, one for the merged nodes, whose keys come out in nondecreasing order) give an O(n)O(n) construction.

Edge cases. n=2n = 2: one merge, codewords 0 and 1. Equal frequencies: any tie-breaking among equal keys is allowed; different trees may arise, but all are optimal. Zero frequency is excluded (a zero-frequency symbol can be dropped before coding).

Mathematical explanation

Greedy-choice property

Lemma (CLRS 3e, Section 16.3). Let xx and yy be two symbols of lowest frequency. There exists an optimal prefix code in which the codewords for xx and yy have the same length and differ only in the last bit (they are siblings in the tree).

Idea. Order the two minimum frequencies as f(x)≤f(y)f(x)\le f(y). Choose deepest sibling leaves a,ba,b, ordered so f(a)≤f(b)f(a)\le f(b). After resolving coincident symbols by relabelling, f(x)≤f(a)f(x)\le f(a) and f(y)≤f(b)f(y)\le f(b). Move the lower-frequency symbols to those deeper positions by exchanges. Each exchange changes cost by (f(x)−f(a))(d(a)−d(x))≤0(f(x)-f(a))(d(a)-d(x))\le0, or the analogous expression for y,by,b. Thus an optimal tree exists with x,yx,y deepest siblings.

Optimal substructure

Replace xx and yy by a single symbol zz of frequency f(x)+f(y)f(x) + f(y). An optimal tree for the reduced alphabet, expanded by making xx and yy the children of zz, is optimal for the original alphabet. The cost increases by exactly f(x)+f(y)f(x) + f(y) (one extra bit on every occurrence of xx or yy).

Together, the two properties justify the algorithm: each merge is a safe greedy choice, and the residual problem is again a Huffman instance.

Equivalent cost formula

B(T)=∑internal node zf(z),B(T) = \sum_{\text{internal node } z} f(z),

where f(z)f(z) is the sum of the frequencies of the leaves in zz's subtree (equivalently, the sum of the frequencies of zz's two children). This matches the total merge cost in an optimal merge pattern.

Worked examples

Five symbols

Frequencies: a:45a:45, b:13b:13, c:12c:12, d:16d:16, e:9e:9.

StepExtractNew node freqQueue keys (ascending)
start9, 12, 13, 16, 45
1e=9e=9, c=12c=12z1=21z_1 = 2113, 16, 21, 45
2b=13b=13, d=16d=16z2=29z_2 = 2921, 29, 45
3z1=21z_1=21, z2=29z_2=29z3=50z_3 = 5045, 50
4a=45a=45, z3=50z_3=50root =95= 9595

Codewords (left = 0, right = 1; children ordered as extracted):

SymbolPathCodewordLength
aaleft of root01
eeright-left-left1003
ccright-left-right1013
bbright-right-left1103
ddright-right-right1113

At the root, aa (extracted first in step 4) is the left child and z3z_3 the right; inside z3z_3, z1z_1 is left and z2z_2 right. The exact bit strings depend on this left/right convention; the lengths do not. Weighted external path length:

B=45⋅1+13⋅3+12⋅3+16⋅3+9⋅3=45+39+36+48+27=195.B = 45\cdot 1 + 13\cdot 3 + 12\cdot 3 + 16\cdot 3 + 9\cdot 3 = 45 + 39 + 36 + 48 + 27 = 195.

Check via internal nodes: 21+29+50+95=19521 + 29 + 50 + 95 = 195.

Huffman tree built from five symbol frequencies
Figure 1. Huffman tree for frequencies a:45a:45, b:13b:13, c:12c:12, d:16d:16, e:9e:9: successive merges produce internal nodes of frequencies 21, 29, 50 and 95, and B(T)=195B(T) = 195.

Optimal merge of four files

Lengths 20, 30, 10, 25. Merges:

  1. 10+20=3010 + 20 = 30 (cost 30); remaining 25, 30, 30.
  2. 25+30=5525 + 30 = 55 (cost 55); remaining 30, 55.
  3. 30+55=8530 + 55 = 85 (cost 85).

Total cost 30+55+85=17030 + 55 + 85 = 170. The cost depends only on which runs end up merged together (the shape of the merge tree), not on the order in which independent merges are carried out. Merging the two largest first (30 with 25, then 55 with 20, then 75 with 10) costs 55+75+85=21555 + 75 + 85 = 215, which is worse.

Decoding a bit string

With the code of the five-symbol example (a=0a = 0, e=100e = 100, c=101c = 101, b=110b = 110, d=111d = 111), decode 1100101111. Walk from the root and restart at the root at each leaf: 110 gives bb, 0 gives aa, 101 gives cc, 111 gives dd. The message is bacdbacd. No separators are needed because no codeword is a prefix of another.

Ties can change the codeword lengths

Frequencies 1,1,2,21, 1, 2, 2 (symbols p,q,r,sp, q, r, s). The first merge is forced: p+q=2p + q = 2. Now three keys equal 2 (the new node and rr, ss).

  • Merge rr with ss: lengths p,q,r,s=2,2,2,2p, q, r, s = 2, 2, 2, 2, cost 2+2+4+4=122+2+4+4 = 12.
  • Merge the new node with rr: lengths 3,3,2,13, 3, 2, 1, cost 3+3+4+2=123+3+4+2 = 12.

Both trees are optimal, but the maximum codeword length (2 versus 3) and the set of lengths differ. A question that asks for "the" length of a symbol must fix a tie-breaking rule.

Average length against entropy

With probabilities pc=f(c)/∑fp_c = f(c) / \sum f, the average length L=∑pcℓcL = \sum p_c \ell_c of an optimal prefix code satisfies H≤L<H+1H \le L < H + 1, where H=−∑pclg⁡pcH = -\sum p_c \lg p_c is the entropy (in bits per symbol). For the five-symbol example, L=195/95≈2.053L = 195/95 \approx 2.053 and H≈2.035H \approx 2.035.

Important properties and observations

  • Huffman codes are optimal among all binary prefix codes. By the Kraft-McMillan inequality (∑c2−ℓc≤1\sum_c 2^{-\ell_c} \le 1), any uniquely decodable code's lengths can be met by a prefix code, so Huffman is also optimal among all uniquely decodable symbol-by-symbol codes. An optimal (full) tree satisfies ∑c2−ℓc=1\sum_c 2^{-\ell_c} = 1 exactly.
  • The longest codeword can have length n−1n - 1. Fibonacci-like frequencies 1,1,2,3,5,8,13,211, 1, 2, 3, 5, 8, 13, 21 build a completely skewed tree: the two 1s get length 7 and 21 gets length 1.
  • The code is not unique: swapping left and right children, or breaking frequency ties differently, changes bit strings but not B(T)B(T).
  • Average codeword length is B(T)/∑f(c)B(T) / \sum f(c). For the example, 195/95≈2.05195 / 95 \approx 2.05 bits per symbol, against ⌈lg⁡5⌉=3\lceil \lg 5 \rceil = 3 for a fixed-length code.
  • If one frequency exceeds the sum of all the others, that symbol is merged last and gets a 1-bit codeword. The condition is sufficient, not necessary: a=45a = 45 is below 13+12+16+9=5013+12+16+9 = 50 yet still gets length 1 above.
  • Alphabet size 1. A single symbol needs zero payload bits only if the message length is supplied out of band; otherwise use, for example, the one-bit codeword 0 per occurrence with suitable message framing; the algorithm assumes n≥2n \ge 2.

Common misconceptions.

  • "Huffman always beats a fixed-length code." With all frequencies equal and nn a power of 2, every codeword has length lg⁡n\lg n, exactly a fixed-length code. For other nn, lengths are ⌊lg⁡n⌋\lfloor \lg n \rfloor and ⌈lg⁡n⌉\lceil \lg n \rceil: five equal frequencies give lengths 3,3,2,2,23, 3, 2, 2, 2, average 2.4 bits against 3.
  • "Any greedy merge of files is optimal." Only repeatedly merging the two currently shortest runs is guaranteed; other orders can cost more.
  • "Each symbol's codeword length is fixed." Only the cost B(T)B(T) is fixed. Tie-breaking can change both individual lengths and the maximum length, as the 1,1,2,21, 1, 2, 2 example shows.

GATE examination perspective

  • TRACE THE HEAP. Questions give frequencies and ask for the next merge, the final B(T)B(T), or a codeword length.
  • INTERNAL-NODE SUM. Computing B(T)B(T) as the sum of internal-node frequencies is faster than walking every leaf.
  • TIES. State how ties are broken; lengths stay optimal either way.
  • MERGE PATTERNS. Same algorithm, cost = sum of merge sizes; do not confuse with the final combined file size alone.
  • PREFIX PROPERTY. Instant decode: reading bits walks the tree until a leaf.
  • COUNTS. nn symbols give n−1n-1 merges, n−1n-1 internal nodes and 2n−12n-1 nodes. The longest codeword is at most n−1n-1 bits.
  • AVERAGE LENGTH. Divide B(T)B(T) by the total frequency (or use probabilities directly). Compare with ⌈lg⁡n⌉\lceil \lg n \rceil for "bits saved" questions.
  • MERGE COST MODEL. Merge-pattern cost counts records moved (a+ba+b per merge). Merging two sorted runs needs at most a+b−1a+b-1 comparisons; read which quantity the question wants.

Summary

Sources

  1. T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 3rd ed., MIT Press, 2009: Chapter 16, Section 16.3 (Huffman codes).

Next steps