G27
Self-checkedTier 1 14 min readalgo.huffman-coding

Huffman coding

Optimal prefix codes: variable-length codes, the prefix property and the Kraft inequality, Huffman's algorithm (repeatedly merge the two least frequent symbols, with a min-heap in O(n log n)), the cost as the sum of the weights of the internal nodes, a worked tree and code table, why the greedy choice is optimal, decoding, tie-breaking, extreme shapes of the tree, and the entropy bounds.

Why it exists

Text, images and files are stored as bit strings. A fixed-length code gives every symbol the same number of bits (⌈log⁡2n⌉\lceil \log_2 n \rceil for nn symbols), which wastes space when some symbols are far more frequent than others (the letter ee against zz). Huffman coding gives frequent symbols short code words and rare ones long ones, in the best possible way: it produces the prefix code with the smallest average length. The algorithm is a textbook greedy algorithm (always merge the two least frequent), its proof is an exchange argument, and its implementation is a heap, so it is where the greedy method and the priority queue meet.

Prerequisites

You need the greedy method and its exchange proofs (greedy method) and the min-heap (binary heap).

Precise definitions

Code and code word. A code assigns to each symbol a string of bits, its code word. A message is encoded by concatenating the code words of its symbols.

Prefix code. No code word is a prefix (beginning) of another. Then the bit string can be decoded from left to right with no separators and no look-ahead: when the bits read so far equal a code word, that symbol is output. A prefix code corresponds to a binary tree whose leaves are the symbols; the code word of a leaf is the path from the root (0 for left, 1 for right).

Cost. For frequencies fif_i and code word lengths ℓi\ell_i (the depth of the leaf), the cost is B=∑ifiℓiB = \sum_i f_i \ell_i (the number of bits of the encoded message, if fif_i counts the occurrences). The average code length is B/∑fiB / \sum f_i. An optimal code minimises it.

Kraft inequality. A prefix code with code word lengths ℓ1,…,ℓn\ell_1, \ldots, \ell_n exists if and only if ∑i2−ℓi≤1\sum_i 2^{-\ell_i} \le 1. It holds with equality exactly for full binary trees (every internal node has two children), and an optimal code is always full.

Entropy. H=−∑ipilog⁡2piH = -\sum_i p_i \log_2 p_i with pi=fi/∑fjp_i = f_i / \sum f_j. No code can have an average length below HH, and the Huffman code satisfies H≤average length<H+1H \le \text{average length} < H + 1.

How it works

The algorithm

  1. Make a node for each symbol, with its frequency as weight.
  2. While more than one node is left: remove the two nodes of smallest weight, make a new node with them as children (the smaller on the left, say) and the sum of their weights as weight, and insert it back.
  3. The last node is the root. Read the code words from the root: 00 for left, 11 for right.

With a min-heap each of the n−1n - 1 merges costs O(log⁡n)O(\log n) (two extractions and one insertion): total O(nlog⁡n)O(n \log n). With a plain sorted array or list it is O(n2)O(n^2); the C program below uses the simple version because it is short, with the same result.

The program runs the algorithm for six symbols with the frequencies A=35A = 35, B=22B = 22, C=17C = 17, D=11D = 11, E=9E = 9, F=6F = 6 (per 100100 symbols), prints every merge and the forest after it, then the code words.

#include <stdio.h>
 
#define MAXN 16
 
static int weight[2 * MAXN], left_[2 * MAXN], right_[2 * MAXN], total_nodes;
static char symbol[2 * MAXN];
 
static void show(int node) {                    /* prints a tree as nested parentheses: (left right) */
    if (left_[node] < 0) { printf("%c", symbol[node]); return; }
    printf("(");
    show(left_[node]);
    printf(" ");
    show(right_[node]);
    printf(")");
}
 
static void assign(int node, char *prefix, int depth, char codes[][MAXN]) {
    if (left_[node] < 0) { prefix[depth] = 0; for (int i = 0; i <= depth; i++) codes[symbol[node] - 'A'][i] = prefix[i]; return; }
    prefix[depth] = '0'; assign(left_[node], prefix, depth + 1, codes);
    prefix[depth] = '1'; assign(right_[node], prefix, depth + 1, codes);
}
 
int main(void) {
    const char *names = "ABCDEF";
    int freq[6] = {35, 22, 17, 11, 9, 6};
    int live[2 * MAXN], nlive = 6, cost = 0;
    for (int i = 0; i < 6; i++) { weight[i] = freq[i]; symbol[i] = names[i]; left_[i] = right_[i] = -1; live[i] = i; }
    total_nodes = 6;
    for (int step = 1; nlive > 1; step++) {
        int lo = 0, lo2 = -1;                              /* positions in live[] of the smallest and second smallest weight */
        for (int i = 1; i < nlive; i++) if (weight[live[i]] < weight[live[lo]]) lo = i;
        for (int i = 0; i < nlive; i++) if (i != lo && (lo2 < 0 || weight[live[i]] < weight[live[lo2]])) lo2 = i;
        int x = live[lo], y = live[lo2], z = total_nodes++;
        weight[z] = weight[x] + weight[y];
        left_[z] = x;
        right_[z] = y;
        cost += weight[z];
        printf("step %d: merge ", step); show(x); printf(":%d and ", weight[x]); show(y); printf(":%d -> %d (cost so far %d)\n", weight[y], weight[z], cost);
        live[lo] = z;                                      /* the new node replaces the first, the last live node fills the gap */
        live[lo2] = live[nlive - 1];
        nlive--;
        printf("  forest:");
        for (int i = 0; i < nlive; i++) { printf(" "); show(live[i]); printf(":%d", weight[live[i]]); }
        printf("\n");
    }
    char codes[6][MAXN], prefix[MAXN];
    assign(live[0], prefix, 0, codes);
    int bits = 0;
    for (int i = 0; i < 6; i++) {
        int len = 0;
        while (codes[i][len]) len++;
        bits += freq[i] * len;
        printf("code %c freq %2d %s\n", names[i], freq[i], codes[i]);
    }
    printf("total bits per 100 symbols: %d (fixed length: %d)\n", bits, 300);
    return 0;
}
step 1: merge F:6 and E:9 -> 15 (cost so far 15)
  forest: A:35 B:22 C:17 D:11 (F E):15
step 2: merge D:11 and (F E):15 -> 26 (cost so far 41)
  forest: A:35 B:22 C:17 (D (F E)):26
step 3: merge C:17 and B:22 -> 39 (cost so far 80)
  forest: A:35 (D (F E)):26 (C B):39
step 4: merge (D (F E)):26 and A:35 -> 61 (cost so far 141)
  forest: (C B):39 ((D (F E)) A):61
step 5: merge (C B):39 and ((D (F E)) A):61 -> 100 (cost so far 241)
  forest: ((C B) ((D (F E)) A)):100
code A freq 35 11
code B freq 22 01
code C freq 17 00
code D freq 11 100
code E freq  9 1011
code F freq  6 1010
total bits per 100 symbols: 241 (fixed length: 300)

Huffman's algorithm on frequencies 35, 22, 17, 11, 9, 6: start

Computed by a script, not typed
stepthe two smallest nodes (tree:weight)new weightforest after the merge (tree:weight)sum of new weights so far
step 1
step 2
step 3
step 4
step 5

Step 0

Six symbols A to F with frequencies 35, 22, 17, 11, 9, 6 (per 100 symbols). Repeatedly the two nodes of smallest weight are replaced by one node whose weight is their sum, until one tree is left.

0 / 5
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-greedy-traces.py

The two smallest at first are F=6F = 6 and E=9E = 9, merged into 1515; then D=11D = 11 with that 1515 gives 2626; C=17C = 17 and B=22B = 22 give 3939; 2626 and A=35A = 35 give 6161; at last 3939 and 6161 give the root, 100100. The final tree (in nested notation) is ((C B) ((D (F E)) A))((C\ B)\ ((D\ (F\ E))\ A)).

The Huffman code: start

Computed by a script, not typed
symbolfrequencycode wordlengthfrequency x length
A
B
C
D
E
F

Step 0

Reading the tree from the root: 0 for the left branch (the smaller subtree) and 1 for the right. No code word is the beginning of another, so a bit string decodes in only one way. Total 241 bits per 100 symbols, against 300 for a fixed 3-bit code.

0 / 6
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-greedy-traces.py

Reading the tree: A=11A = 11, B=01B = 01, C=00C = 00, D=100D = 100, E=1011E = 1011, F=1010F = 1010. The frequent symbols have two bits, the rare ones four.

The cost without the code words. Each merge creates one internal node whose weight is the sum of the frequencies below it; a symbol at depth ℓ\ell is counted in ℓ\ell internal nodes (all its ancestors). So B=∑ifiℓi=∑internal nodesweight.B = \sum_i f_i \ell_i = \sum_{\text{internal nodes}} \text{weight}. Here 15+26+39+61+100=24115 + 26 + 39 + 61 + 100 = 241: 241 bits per 100 symbols, an average of 2.412.41 bits, against 300300 (3 bits each) for a fixed-length code, a saving of 19.7%19.7\%. (The merge table shows this running sum.)

Decoding. Read bits until they equal a code word: 1 1 0 1 0 0 1 0 1 11\,1\,0\,1\,0\,0\,1\,0\,1\,1 is 11 01 00 101111\,01\,00\,1011 = A B C EA\,B\,C\,E. Because no code word is a prefix of another, the first match is the only possible one.

Why it is optimal

Greedy choice. Let xx and yy be the two least frequent symbols. In an optimal tree the deepest leaves are the least frequent symbols (otherwise swapping a deeper, more frequent symbol with a shallower, less frequent one lowers the cost: an exchange argument), and the deepest level contains two sibling leaves (an optimal tree is full). So there is an optimal tree in which xx and yy are siblings at the deepest level: merging them first loses nothing.

Optimal substructure. Replace xx and yy by one symbol zz of frequency fx+fyf_x + f_y. The cost of a tree for the original symbols equals the cost of the corresponding tree for the smaller alphabet plus fx+fyf_x + f_y (the extra depth of the two leaves). So an optimal tree for the original problem comes from an optimal tree for the smaller problem; by induction on nn, Huffman's algorithm is optimal. ■\blacksquare

The result was also tested exhaustively: for random frequency sets the Huffman cost equalled the minimum over all code length assignments that form a complete prefix code.

Properties and shapes

  • The code is not unique. Ties between equal weights, and the choice of which child is 00, give different trees; all have the same cost (the minimum) but possibly different code word lengths.
  • Number of nodes. nn leaves and n−1n - 1 internal nodes (a full binary tree), so n−1n - 1 merges.
  • Equal frequencies, n=2kn = 2^k: every code word has kk bits: Huffman gives the fixed-length code. For other nn with equal frequencies the lengths are ⌊log⁡2n⌋\lfloor \log_2 n \rfloor or ⌈log⁡2n⌉\lceil \log_2 n \rceil.
  • Most skewed tree: the Fibonacci frequencies 1,1,2,3,5,8,…1, 1, 2, 3, 5, 8, \ldots give a chain: the rarest symbols get codes of n−1n - 1 bits.
  • Entropy: the average length LL satisfies H≤L<H+1H \le L < H + 1. For frequencies that are all powers of 1/21/2 (such as 12,14,18,18\tfrac12, \tfrac14, \tfrac18, \tfrac18) it equals HH exactly.
  • Assumptions: it is optimal among codes that give each symbol a separate code word, for a known, fixed frequency table (which must also be stored or transmitted); adaptive and block-based codes can do better.

Worked examples

EX 1Build a Huffman tree

Easy

Frequencies a=5a = 5, b=9b = 9, c=12c = 12, d=13d = 13. Merge a,b→14a, b \to 14. Nodes: c=12c = 12, d=13d = 13, 1414. Merge c,d→25c, d \to 25. Nodes: 1414, 2525. Merge →39\to 39. The cost is the sum of the new weights: 14+25+39=7814 + 25 + 39 = 78. Check with the depths: the tree is ((a b) (c d))((a\ b)\ (c\ d)), all four leaves have depth 22, so the cost is 2⋅(5+9+12+13)=782 \cdot (5 + 9 + 12 + 13) = 78 ✓. Codes: a=00a = 00, b=01b = 01, c=10c = 10, d=11d = 11: the same as the fixed-length code, because the frequencies are close together.

EX 2Compare with a fixed-length code

Easy

For the table of this page (66 symbols) a fixed-length code needs ⌈log⁡26⌉=3\lceil \log_2 6 \rceil = 3 bits per symbol: 300300 bits per 100100 symbols. Huffman needs 241241. A message of 10 00010\,000 symbols with these frequencies takes about 24 10024\,100 bits instead of 30 00030\,000.

EX 3Which sets of lengths can be a prefix code?

Medium

Kraft: lengths 1,2,3,31, 2, 3, 3: 12+14+18+18=1\frac12 + \frac14 + \frac18 + \frac18 = 1: a complete prefix code exists (0,10,110,1110, 10, 110, 111). Lengths 1,2,2,31, 2, 2, 3: 12+14+14+18=98>1\frac12 + \frac14 + \frac14 + \frac18 = \frac98 > 1: no prefix code has these lengths. Lengths 2,2,32, 2, 3: sum 58<1\frac58 < 1: a prefix code exists but it is not complete, so it is not optimal (a length can be shortened).

EX 4Cost from the merge weights

Medium

Frequencies 1,1,2,4,81, 1, 2, 4, 8. Merge 1+1=21 + 1 = 2; nodes 2,2,4,82, 2, 4, 8: merge 2+2=42 + 2 = 4; nodes 4,4,84, 4, 8: merge 4+4=84 + 4 = 8 (either pair of equal 44s, same cost); nodes 8,88, 8: merge =16= 16. Cost =2+4+8+16=30= 2 + 4 + 8 + 16 = 30. Check with depths: the symbols with frequency 88 and 44 and 22 get lengths 1,2,31, 2, 3 and the two rarest get 44: 8⋅1+4⋅2+2⋅3+1⋅4+1⋅4=8+8+6+4+4=308 \cdot 1 + 4 \cdot 2 + 2 \cdot 3 + 1 \cdot 4 + 1 \cdot 4 = 8 + 8 + 6 + 4 + 4 = 30 ✓. This is the chain shape: depth n−1=4n - 1 = 4.

EX 5Typical questions

GATE level

(a) Number of merges for nn symbols: n−1n - 1; time with a heap: O(nlog⁡n)O(n \log n). (b) For frequencies 20,20,20,20,2020, 20, 20, 20, 20 how many bits does the longest code word have? Five equal frequencies: lengths are 22 or 33, so the longest has 33 bits. (c) Is {0,01,11,001}\{0, 01, 11, 001\} a prefix code? No: 00 is a prefix of 0101 and of 001001. (d) Does every set of frequencies have a unique Huffman code? No: ties and the labelling of branches give several codes, all with the same minimum cost. (e) If all symbols have frequencies that are powers of two (12,14,18,18\tfrac12, \tfrac14, \tfrac18, \tfrac18): lengths 1,2,3,31, 2, 3, 3 and the average length equals the entropy (1.751.75 bits).

Cheat box

Cheat box

  • Prefix code: no code word is a prefix of another; leaves of a binary tree; decodable left to right.
  • Cost =∑fiℓi== \sum f_i \ell_i = sum of the weights of the internal nodes. Fixed-length: ⌈log⁡2n⌉\lceil \log_2 n \rceil bits.
  • Huffman: repeatedly merge the two least frequent; n−1n - 1 merges; with a min-heap O(nlog⁡n)O(n \log n).
  • Optimal by exchange: the two rarest symbols can be sibling leaves at the deepest level.
  • Not unique (ties, labelling), but the cost is. Kraft: ∑2−ℓi≤1\sum 2^{-\ell_i} \le 1 (equality for full trees).
  • Entropy H≤L<H+1H \le L < H + 1. Equal frequencies, n=2kn = 2^k: all lengths kk. Fibonacci frequencies: a chain.

Traps and GATE patterns

Connections

Huffman's algorithm is a greedy algorithm (greedy method) that uses a min-heap (binary heap, heap applications). Like activity selection and fractional knapsack its proof is an exchange argument.

PYQs

5 previous year questions from your book. I re-solved each one myself (5 by running or simulating, 0 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2021 · Set 2 · 2 marksQ14 · page 115 of the book
Consider the string abbccddeee. Each letter in
the string must be assigned a binary code
satisfying the following properties:
For any two letters, the code assigned to one
letter must not be a prefix of the code assigned
to the other letter.
For any two letters of the same frequency, the
letter which occurs earlier in the dictionary order
is assigned a code whose length is at most the
length of the code assigned to the other letter.
Among the set of all binary code assignments
which satisfy the above two properties, what is
the minimum length of the encoded string?
  • (a)21
  • (b)23
  • (c)25
  • (d)30
GATE 2017 · Set 2 · NATQ25 · page 117 of the book
A message is made up entirely of characters from
the set X = {P,Q,R,S,T} . The table of
probabilities of each character is shown below :

Character
Probability
P
0.22
Q
0.17
R
0.34
S
0.19
T
0.08
Total
1.00
A message of 100 characters over X is encoded
using Huffman coding. Then the excepted length
of the encoded message in bits is
GATE 2007 · MCQ · 1 markQ40 · page 119 of the book
Suppose the letters a, b, c, d, e, f have probabilities
1/2, 1/4, 1/8, 1/16, 1/32, 1/32 respectively.
What is the average length of the Huffman code for
the letters a,b,c,d,e,f?
  • (a)3
  • (b)2.1875
  • (c)2.25
  • (d)1.9375
GATE 2007 · MCQ · 1 markQ41 · page 119 of the book
Suppose the letters a, b, c, d, e, f have probabilities
1/2, 1/4, 1/8, 1/16, 1/32, 1/32 respectively.
Which of the following is the Huffman code for
the letter a, b, c, d, e, f?
  • (a)0, 10, 110, 1110, 11110, 11111
  • (b)11, 10, 011, 010, 001, 000
  • (c)11, 10, 01, 001, 0001, 0000
  • (d)110, 100, 010, 000, 001, 111 ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
year not read yetQ42 · page 120 of the book
The characters a to h have the set of frequencies
based on the first 8 Fibonacci numbers as
follows
a:1, b:1, c:2, d:3, e:5, f:8, g:13, h:21
A Huffman code is used to represent the
characters. What is the sequence of characters
corresponding to the following code?
110111100111010
  • (a)fdheg
  • (b)ecgdf
  • (c)dchfg
  • (d)fehdg

Self-check

Question 1

Frequencies 3,7,10,15,25,403, 7, 10, 15, 25, 40. What is the cost of the Huffman code (total bits)?

Show answer

Merge 3+7=103 + 7 = 10; nodes 10,10,15,25,4010, 10, 15, 25, 40: 10+10=2010 + 10 = 20; nodes 15,20,25,4015, 20, 25, 40: 15+20=3515 + 20 = 35; nodes 25,35,4025, 35, 40: 25+35=6025 + 35 = 60; nodes 40,6040, 60: 100100. Cost 10+20+35+60+100=22510 + 20 + 35 + 60 + 100 = 225.

Question 2

Can a prefix code have code word lengths 1,1,21, 1, 2?

Show answer

No: 12+12+14>1\frac12 + \frac12 + \frac14 > 1 (Kraft). After using 00 and 11 no longer code word is available.

Question 3

What is the running time of Huffman's algorithm with a min-heap for nn symbols?

Show answer

O(nlog⁡n)O(n \log n): n−1n - 1 merges, each O(log⁡n)O(\log n).

Question 4

Why are the two rarest symbols sibling leaves at the deepest level in some optimal tree?

Show answer

A more frequent symbol deeper than a rarer one can be swapped with it, lowering the cost; and an optimal tree is full, so the deepest level has two sibling leaves.

Revision card

One-screen revision

  • Prefix code = leaves of a binary tree; cost ∑fiℓi\sum f_i \ell_i = sum of internal node weights.
  • Huffman: merge the two smallest repeatedly; n−1n - 1 merges; heap O(nlog⁡n)O(n \log n); optimal (exchange + substructure).
  • Kraft ∑2−ℓ≤1\sum 2^{-\ell} \le 1; H≤L<H+1H \le L < H + 1.
  • Not unique, cost unique. Equal frequencies 2k2^k: kk bits each; Fibonacci: chain.

References

  • ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Section 16.3 Huffman codes
  • ·Kleinberg and Tardos, Algorithm Design, Section 4.8 Huffman codes and data compression
  • ·Sedgewick and Wayne, Algorithms (4th edition), Section 5.5 Data compression (Huffman compression)

Verification

The Huffman cost was compared with the minimum over EVERY assignment of code lengths that forms a complete prefix code (Kraft sum equal to one), for 150 random frequency sets of up to 6 symbols: always equal, and equal under two different tie-breaking rules. The Kraft inequality was checked in both directions (code words can be constructed when the sum is at most 1; for small cases no prefix code exists when it exceeds 1). The entropy bounds H <= average length < H + 1 held on 300 random frequency sets. The page example (frequencies 35, 22, 17, 11, 9, 6: cost 241 against 300 for a 3-bit code) was produced by the C program on this page, whose tree and codes were recomputed in Python; random strings decode uniquely with the code. The shapes (Fibonacci frequencies give a chain, equal frequencies give balanced codes) were confirmed for n up to 9. Textbook references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never