DrawCode Algorithm Visualizer • Greedy • Hard

Huffman Coding (Greedy)

Tags: Greedy, Heap, Compression, Prefix codes, Trees

1. One-Liner

Huffman coding merges the two smallest frequency nodes until one tree remains, yielding a minimum expected codeword length for a given symbol distribution (prefix-free).


2. The Problem It Solves

Symbols appear with known frequencies. Assign binary codes so frequent symbols get shorter bitstrings, no code is a prefix of another, and average bits per symbol is minimized.


3. The Core Idea

Always combine the two lightest pieces—locally optimal merges build a globally optimal tree (Kraft–McMillan + greedy proof). Like merging piles of paper: smallest piles first keeps depth balanced for heavy items near the root.


4. How It Works (Step-by-Step)

StepWhat Happens
1. LeavesEach symbol is a node with its weight
2. Min-heapInsert all nodes by frequency
3. MergePop two mins, create parent with sum weight, push back
4. RepeatUntil one node remains—the Huffman tree
5. CodesLabel edges 0/1; read leaf paths

5. Dry Run Example

Frequencies A:5, B:9, C:12, D:13, E:16, F:45. Repeatedly merge smallest pairs; frequent F ends up shallow (short code), rare symbols deeper.


6. Key Properties

PropertyValue
OptimalFor fixed frequencies & binary alphabet
Prefix-freeValid codewords from leaves
GreedyTwo smallest combine

7. Where It Is Used

DomainUse
CompressionDEFLATE family, historical file compressors
TheoryEntropy, coding bounds

8. Interview Tips

Mention min-heap, O(n log n) build, tie-breaking doesn’t break optimality, contrast with fixed-length codes and arithmetic coding.


9. Comparison with Other Approaches

ApproachAvg lengthNotes
HuffmanNear entropyInteger bit lengths per symbol
Fixed 8-bitWorseNo adaptation
ArithmeticCan beat Huffman per symbolFractional bits

10. Complexity

MetricValue
TimeO(n log n) with n symbols (heap ops)
SpaceO(n) for tree and heap

Implementation Example (PYTHON)

import heapq
def huffman_tree(freq):
    heap = [[w, [sym, '']] for sym, w in freq.items()]
    heapq.heapify(heap)
    while len(heap) > 1:
        lo = heapq.heappop(heap)
        hi = heapq.heappop(heap)
        for p in lo[1:]:
            p[1] = '0' + p[1]
        for p in hi[1:]:
            p[1] = '1' + p[1]
        heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])
    return heap[0][1:]

Interactive Visualizer Workspace

Explore step-by-step interactive animations, memory state tracking, and live multi-language execution in DrawCode.

Launch Interactive Visualizer