Back to the on-screen lesson ·

Huffman's algorithm

Merging the two least probable symbols repeatedly; reading lengths and average length.

Paper packet. Every task here also exists on screen, where it is checked automatically; answers written on paper are not assessed by Nydus. When you are back at a device, enter your answers there.

1. What you will learn

By the end of this lesson you will be able to run Huffman's algorithm by hand and in code, read codeword lengths and codewords from the resulting tree, compute the average length as the sum of the merged weights, and compare it with the entropy. You will prove that Huffman codes are optimal among all uniquely decodable symbol codes through the exchange argument and induction, explain why the gap to the entropy is always below one bit and vanishes exactly for dyadic sources, and say what techniques recover the remaining fraction of a bit.

2. Huffman's algorithm

Huffman's algorithm builds an optimal prefix code from the bottom up. Start with each symbol as a weight equal to its probability. Repeatedly take the two smallest weights, join them under a new node whose weight is their sum, and put that node back in the list; stop when one node remains. Reading the tree from the root, left branch $0$ and right branch $1$, gives the codewords; a symbol's length is the number of merges above it. A useful shortcut: every merge adds one bit to every symbol beneath it, so the average length is the sum of all merged weights. For $(0.4, 0.3, 0.2, 0.1)$ the merges are $0.3, 0.6, 1$, so $L = 1.9$ bits with lengths $1, 2, 3, 3$, against $H = 1.846$. Ties may be broken either way; different trees can result, all with the same optimal $L$. For dyadic probabilities the algorithm reproduces the Shannon lengths and $L = H$.

Another way: picture

Four leaves labelled $0.4, 0.3, 0.2, 0.1$. The two lightest join into a node $0.3$; it joins the other $0.3$ into $0.6$; that joins $0.4$ at the root. Reading down: $0.4 \to 0$, $0.3 \to 10$, $0.2 \to 110$, $0.1 \to 111$.

Another way: steps

  1. List the probabilities as weights.
  2. Merge the two smallest into their sum; record the sum.
  3. Repeat until one weight remains.
  4. Average length $=$ sum of the recorded merges; codewords from the tree, $0$ left and $1$ right.

3. A full trace, and the sum-of-merges shortcut

Run the algorithm on $(0.4, 0.3, 0.2, 0.1)$, always merging the two smallest weights:

steplist of weightsmergenew weight
$1$$0.4, 0.3, 0.2, 0.1$$0.2 + 0.1$$0.3$
$2$$0.4, 0.3, 0.3$$0.3 + 0.3$$0.6$
$3$$0.6, 0.4$$0.6 + 0.4$$1.0$
total$0.3 + 0.6 + 1.0$$L = 1.9$
A Huffman tree for probabilities 0.4, 0.3, 0.2 and 0.1: the two lightest leaves 0.2 and 0.1 merge into 0.3, that merges with the leaf 0.3 into 0.6, and 0.6 merges with 0.4 at the root 1.0. The merged weights 0.3 + 0.6 + 1.0 add to the average length 1.9 bits.
A Huffman tree for probabilities 0.4, 0.3, 0.2 and 0.1: the two lightest leaves 0.2 and 0.1 merge into 0.3, that merges with the leaf 0.3 into 0.6, and 0.6 merges with 0.4 at the root 1.0. The merged weights 0.3 + 0.6 + 1.0 add to the average length 1.9 bits.

The tree gives lengths $1, 2, 3, 3$ and, reading left $= 0$ and right $= 1$, codewords such as $0, 10, 110, 111$. The shortcut in the last row is worth memorising: every merge pushes everything beneath it one level deeper, adding its own weight to the average length, so $$L = \text{sum of all merged weights}.$$ Here $0.3 + 0.6 + 1.0 = 1.9$, and the direct sum $0.4 \cdot 1 + 0.3 \cdot 2 + 0.2 \cdot 3 + 0.1 \cdot 3 = 1.9$ agrees. The shortcut is faster and needs no codewords at all.

4. The table the practice draws from

Every practice distribution, with its merge sequence, average length, entropy and gap:

distributionHuffman merges$L$$H$gap $L - H$
$(0.4, 0.3, 0.2, 0.1)$$0.2 + 0.1 = 0.3;\ 0.3 + 0.3 = 0.6;\ 0.6 + 0.4 = 1$$1.9$$1.846$$0.054$
$(0.5, 0.25, 0.125, 0.125)$$0.125 + 0.125 = 0.25;\ 0.25 + 0.25 = 0.5;\ 0.5 + 0.5 = 1$$1.75$$1.75$$0$
$(0.6, 0.2, 0.1, 0.1)$$0.1 + 0.1 = 0.2;\ 0.2 + 0.2 = 0.4;\ 0.4 + 0.6 = 1$$1.6$$1.571$$0.029$
$(0.4, 0.2, 0.2, 0.2)$$0.2 + 0.2 = 0.4;\ 0.2 + 0.4 = 0.6;\ 0.4 + 0.6 = 1$$2$$1.922$$0.078$
$(0.35, 0.3, 0.2, 0.15)$$0.2 + 0.15 = 0.35;\ 0.3 + 0.35 = 0.65;\ 0.35 + 0.65 = 1$$2$$1.926$$0.074$
$(0.45, 0.25, 0.15, 0.15)$$0.15 + 0.15 = 0.3;\ 0.25 + 0.3 = 0.55;\ 0.45 + 0.55 = 1$$1.85$$1.840$$0.010$
$(0.3, 0.25, 0.2, 0.15, 0.1)$$0.15 + 0.1 = 0.25;\ 0.2 + 0.25 = 0.45;\ 0.25 + 0.3 = 0.55;\ 0.45 + 0.55 = 1$$2.25$$2.228$$0.022$

Two patterns are worth noticing. The dyadic row $(0.5, 0.25, 0.125, 0.125)$ has gap $0$: the lengths match the surprises exactly. The row $(0.4, 0.2, 0.2, 0.2)$ has the largest gap, $0.078$: four nearly equal symbols force a fixed-length code of $2$ bits while the entropy is $1.922$. Ties in the merge order (two equal smallest weights) may give different trees, but the average length is always the same.

5. Solving the practice problems

  1. Average length for a given distribution: run the merges and add them up. Keep the running list sorted so the two smallest are always in front.
  2. One symbol of $\tfrac{1}{2}$ and $2^j$ of $2^{-(j+1)}$: the distribution is dyadic, so Huffman reaches the entropy: $L = \tfrac{j + 2}{2}$.
  3. The first step on $0.4, 0.3, 0.2, 0.1$: merge the two smallest, $0.2$ and $0.1$, into $0.3$ — never the two largest, and never a fixed pair of positions.

Common mistakes

6. Five symbols

  1. $(0.3, 0.25, 0.2, 0.15, 0.1)$: merge $0.15 + 0.1 = 0.25$; list $0.3, 0.25, 0.25, 0.2$.

    Smallest two first.

  2. Merge $0.2 + 0.25 = 0.45$; list $0.45, 0.3, 0.25$. Merge $0.25 + 0.3 = 0.55$. Merge $0.45 + 0.55 = 1$.

    Ties broken arbitrarily.

  3. $L = 0.25 + 0.45 + 0.55 + 1 = 2.25$ bits; $H = 2.228$; lengths $2, 2, 2, 3, 3$.

    Sum of merges.

7. A dyadic source

  1. $(\tfrac{1}{2}, \tfrac{1}{4}, \tfrac{1}{8}, \tfrac{1}{8})$: merges $\tfrac{1}{4}, \tfrac{1}{2}, 1$.

  2. $L = 1.75 = H$; lengths $1, 2, 3, 3$ match the surprises exactly.

    No loss for dyadic probabilities.

8. Huffman for $(0.45, 0.25, 0.15, 0.15)$

  1. Merge $0.15 + 0.15 = 0.3$; list $0.45, 0.3, 0.25$.

  2. Merge $0.25 + 0.3 = 0.55$; list $0.55, 0.45$.

    Re-sorting matters: $0.3$ is now larger than $0.25$.

  3. Merge $0.45 + 0.55 = 1$; $L = 0.3 + 0.55 + 1 = 1.85$ bits, against $H = 1.840$.

    Lengths $1, 2, 3, 3$; the gap is only $0.010$ bits.

9. Five symbols, with a re-sort in the middle

  1. $(0.3, 0.25, 0.2, 0.15, 0.1)$: merge $0.15 + 0.1 = 0.25$; list $0.3, 0.25, 0.25, 0.2$.

  2. Merge $0.2 + 0.25 = 0.45$; list $0.45, 0.3, 0.25$. Merge $0.25 + 0.3 = 0.55$.

    With a tie at $0.25$, either choice gives the same $L$.

  3. Merge $0.45 + 0.55 = 1$; $L = 0.25 + 0.45 + 0.55 + 1 = 2.25$ bits, against $H = 2.228$.

10. Your turn: Huffman for $(0.6, 0.2, 0.1, 0.1)$

  1. Merges: $0.1 + 0.1 = 0.2$; $0.2 + 0.2 = 0.4$; $0.4 + 0.6 = 1$.

  2. Your turn: work this step out. Its working is at the end of the packet.

    $L = 0.2 + 0.4 + 1 = 1.6$ bits; lengths $1, 2, 3, 3$.

11. Guided practice

Run Huffman's algorithm on the probabilities $(0.35, 0.3, 0.2, 0.15)$. What is the average codeword length, in bits?

Answer:

12. Guided practice

A source has one symbol of probability $\tfrac{1}{2}$ and $16$ symbols of probability $2^{-5}$ each. What average length does Huffman's algorithm achieve, in bits?

Answer:

13. Practice

This program reads a count and then that many probabilities, and prints the average Huffman code length: it repeatedly merges the two smallest weights and adds up what it merged. ``` n = int(input()) p = [float(input()) for _ in range(n)] w = sorted(p) total = 0.0 while len(w) > 1: a = w.pop(0) b = w.pop(0) total += a + b w.append(a + b) w.sort() print(round(total, 4)) ``` What does it print when the input is `4`, then `0.5`, `0.25`, `0.125`, `0.125`?

[__output__]

Write each blank here: output:

14. Practice

Run Huffman's algorithm on the probabilities $(0.4, 0.3, 0.2, 0.1)$. What is the average codeword length, in bits?

Answer:

15. Somewhere new

Probabilities $0.4, 0.3, 0.2, 0.1$. What does the first step of Huffman's algorithm do?

16. Lesson test

Lesson test: one question per skill, one attempt each, no hints. Your answers are checked when you submit.

17. Test question

A source has one symbol of probability $\tfrac{1}{2}$ and $8$ symbols of probability $2^{-4}$ each. What average length does Huffman's algorithm achieve, in bits?

Answer:

18. What you can do now

You can build the best symbol code for any source and say how far it is from the entropy. Next: typical sequences, which explain why long blocks reach the entropy.

Working for the steps left to you

10. Your turn: Huffman for $(0.6, 0.2, 0.1, 0.1)$, step 2