1
WARNING, THESE SLIDES HAVE NOT YET BEEN UPDATED FOR FALL 2026
Compression
2
Lecture 39
CS61B, Spring 2026 @ UC Berkeley
Josh Hug and Manuel Sabin
Today’s Goal: Compression
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
3
Zip Files, How Do They Work?
4
Size in Bytes
$ zip mobydick.zip mobydick.txt
adding: mobydick.txt (deflated 59%)
$ ls -l
-rw-rw-r-- 1 jug jug 643207 Apr 24 10:55 mobydick.txt
-rw-rw-r-- 1 jug jug 261375 Apr 24 10:55 mobydick.zip
File is unchanged by zipping / unzipping.
$ unzip mobydick.zip
replace mobydick.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: r
new name: unzipped.txt
inflating: unzipped.txt
$ diff mobydick.txt unzipped.txt
$
Compression Model #1: Algorithms Operating on Bits
In a lossless algorithm we require that no information is lost.
5
01010101000001010101110...
Compression
Algorithm C
1001010101...
01010101000001010101110...
Decompression
Algorithm C-1
1001010101...
Bitstream B
Compressed bits C(B)
C(B)
B
Prefix Free Codes
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
6
Increasing Optimality of Coding
One common encoding for English text is to represent each letter by a sequence of 8 bits, e.g. ‘d’ is 01100100.
Easy way to compress: Use fewer than 8 bits for each letter.
7
word | binary | hexadecimal |
dog | 01100100 01101111 01100111 | 64 6f 67 |
More Code: Mapping Alphanumeric Symbols to Codewords: yellkey.com/human
Example: Morse code.
8
More Code: Mapping Alphanumeric Symbols to Codewords
Example: Morse code.
Note:
9
Alternate strategy: Avoid ambiguity by making code prefix free.
Morse Code (as a Tree)
10
From Wikimedia
Prefix-Free Codes [Example 1]
A prefix-free code is one in which no codeword is a prefix of any other. Example for English:
11
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
start
space
E
T
A
0
1
O
I
1
0
1
0
1
0
1
0
1
0
1
0
...
Prefix-Free Codes [Example 2]
A prefix-free code is one in which no codeword is a prefix of any other. Example for English:
12
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | |
I ATE: 100011110111101010
start
0
1
space
E
A
T
O
I
...
...
...
1
0
0
1
0
...
1
0
1
0
1
0
1
0
1
0
1
0
1
Prefix Free Code Design
Observation: Some prefix-free codes are better for some texts than others.
Observation: It’d be useful to have a procedure that calculates the “best” code for a given text.
13
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | |
Better for EEEEAT (8+4+3 = 15 bits).
Much worse for JOSH (25+5+8+10 = 48 bits).
Worse for EEEEAT (12+4+4 = 20 bits).
Better for JOSH (7+4+6+6 = 23 bits).
Shannon Fano Codes (Extra)
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
14
Code Calculation Approach #1 (Shannon-Fano Coding)
15
Symbol | Frequency |
我 | 0.35 |
爸 | 0.17 |
是 | 0.17 |
李 | 0.16 |
刚 | 0.15 |
Left half
Right half
我
爸
是
李
刚
35% of all characters are 我
Code Calculation Approach #1 (Shannon-Fano Coding)
16
Symbol | Frequency | Code |
我 | 0.35 | 0... |
爸 | 0.17 | 0... |
是 | 0.17 | 1... |
李 | 0.16 | 1... |
刚 | 0.15 | 1... |
我
爸
是
李
刚
Left half
Right half
0
1
Code Calculation Approach #1 (Shannon-Fano Coding)
17
Symbol | Frequency | Code |
我 | 0.35 | 00 |
爸 | 0.17 | 01 |
是 | 0.17 | 1... |
李 | 0.16 | 1... |
刚 | 0.15 | 1... |
我
爸
是
李
刚
Left half
Right half
1
0
0
1
Code Calculation Approach #1 (Shannon-Fano Coding)
18
Symbol | Frequency | Code |
我 | 0.35 | 00 |
爸 | 0.17 | 01 |
是 | 0.17 | 1... |
李 | 0.16 | 1... |
刚 | 0.15 | 1... |
我
爸
是
李
刚
Left half
Right half
1
0
0
1
Code Calculation Approach #1 (Shannon-Fano Coding)
19
Symbol | Frequency | Code |
我 | 0.35 | 00 |
爸 | 0.17 | 01 |
是 | 0.17 | 10 |
李 | 0.16 | 11... |
刚 | 0.15 | 11... |
我
爸
是
李
刚
Left half
Right half
1
0
0
1
0
1
Code Calculation Approach #1 (Shannon-Fano Coding)
20
Symbol | Frequency | Code |
我 | 0.35 | 00 |
爸 | 0.17 | 01 |
是 | 0.17 | 10 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
我
爸
是
李
刚
1
0
0
1
0
1
0
1
Code Calculation Approach #1 (Shannon-Fano Coding)
Shannon-Fano coding is NOT optimal. Does a good job, but possible to find ‘better’ codes (see CS170).
21
Symbol | Frequency | Code |
我 | 0.35 | 00 |
爸 | 0.17 | 01 |
是 | 0.17 | 10 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
我
爸
是
李
刚
1
0
0
1
0
1
0
1
Huffman Coding: Core Idea
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
22
Code Calculation Approach #2: Huffman Coding
Suppose I have a text file with the 5 chinese characters shown.
23
Symbol | Frequency |
我 | 0.35 |
爸 | 0.17 |
是 | 0.17 |
李 | 0.16 |
刚 | 0.15 |
我
爸
是
李
刚
35% of all characters are 我
Code Calculation Approach #2: Huffman Coding
Calculate relative frequencies.
24
我
爸
是
李
刚
0.35
0.17
0.17
0.16
0.15
我
爸
是
李
刚
0.35
0.17
0.17
0.31
0
1
我
爸
是
李
刚
0.35
0.31
0
1
0.34
0
1
35% of characters in input are 我.
16% of characters in input are 李.
Code Calculation Approach #2: Huffman Coding
Calculate relative frequencies.
25
我
爸
是
李
刚
0.35
0.31
0
1
0.34
0
1
我
爸
是
李
刚
0.35
0
1
0
1
0.65
1
0
我
爸
是
李
刚
0
1
0
1
1
0
0
1
Efficiency Assessment: http://yellkey.com/east
How many bits per symbol do we need to compress a file with the character frequencies listed below using the Huffman code that we created?
26
Symbol | Frequency | Huffman Code |
我 | 0.35 | 0 |
爸 | 0.17 | 100 |
是 | 0.17 | 101 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
A. (1*1 + 4*3) / 5
= 2.6 bits per symbol
B. (0.35) * 1 + (0.17 + 0.17 + 0.16 + 0.15) * 3
= 2.3 bits per symbol
C. Not enough information, we need to know the exact characters in the file being compressed.
Efficiency Assessment of Huffman Coding
How many bits per symbol do we need to compress a file with the character frequencies listed below using the Huffman code that we created?
B. (0.35) * 1 + (0.17 + 0.17 + 0.16 + 0.15) * 3 = 2.3 bits per symbol.
27
Symbol | Frequency | Huffman Code |
我 | 0.35 | 0 |
爸 | 0.17 | 100 |
是 | 0.17 | 101 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
Example assuming we have 100 symbols:
Total: 230 bits
230 / 100 = 2.3 bits/symbol
Efficiency Assessment of Huffman Coding
If we had a file with 350 我 characters , 170 爸 characters , 170 是 characters, 160 李 characters, and 150 刚 characters, how many total bits would we need to encode this file using 32 bit Unicode? Using our Huffman code?
You don’t need a calculator.
28
2.30 bits per symbol for texts with this distribution
Symbol | Frequency | Huffman Code |
我 | 0.35 | 0 |
爸 | 0.17 | 100 |
是 | 0.17 | 101 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
Efficiency Assessment of Huffman Coding
If we had a file with 350 我 characters , 170 爸 characters , 170 是 characters, 160 李 characters, and 150 刚 characters, how many total bits would we need to encode this file using 32 bit Unicode? Using our Huffman code?
1000 total characters.
Space used:
Our code is 14 times as efficient!
29
2.30 bits per symbol for texts with this distribution
Symbol | Frequency | Huffman Code |
我 | 0.35 | 0 |
爸 | 0.17 | 100 |
是 | 0.17 | 101 |
李 | 0.16 | 110 |
刚 | 0.15 | 111 |
Huffman vs. Shannon-Fano
Shannon-Fano code below results in an average of 2.31 bits per symbol, whereas Huffman is only 2.3 bits per symbol.
30
Symbol | Frequency | S-F Code | Huffman Code |
我 | 0.35 | 00 | 0 |
爸 | 0.17 | 01 | 100 |
是 | 0.17 | 10 | 101 |
李 | 0.16 | 110 | 110 |
刚 | 0.15 | 111 | 111 |
Strictly better than Shannon-Fano coding. There is NO downside to Huffman coding instead.
Data Structures for Huffman Coding
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
31
Prefix-Free Codes
Question: For encoding (bitstream to compressed bitstream), what is a natural data structure to use? Assume characters are of type Character, and bit sequences are of type BitSequence.
32
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For encoding (bitstream to compressed bitstream), what is a natural data structure to use? chars are just integers, e.g. ‘A’ = 65. Two approaches:
Compared to HashMaps, Arrays are faster (just get the item from the array), but use more memory if some characters in the alphabet are unused.��
33
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For decoding (compressed bitstream back to bitstream), what is a natural data structure to use?
34
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For decoding (compressed bitstream back to bitstream), what is a natural data structure to use?
35
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For decoding (compressed bitstream back to bitstream), what is a natural data structure to use?
36
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For decoding (compressed bitstream back to bitstream), what is a natural data structure to use?
37
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Prefix-Free Codes
Question: For decoding (compressed bitstream back to bitstream), what is a natural data structure to use?
38
space | 111 |
E | 010 |
T | 1101 |
A | 1011 |
O | 1001 |
I | 1000 |
... | 0111 |
space | 1 |
E | 01 |
T | 001 |
A | 0001 |
O | 00001 |
I | 000001 |
... | |
I ATE: 0000011000100101
I ATE: 100011110111101010
Huffman Coding in Practice
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
39
Huffman Compression
Two possible philosophies for using Huffman Compression:
What are some advantages/disadvantages of each idea? Which is better?�
40
$ java HuffmanEncodePh1 ENGLISH mobydick.txt
$ java HuffmanEncodePh1 BITMAP horses.bmp
$ java HuffmanEncodePh2 mobydick.txt
$ java HuffmanEncodePh2 horses.bmp
Huffman Compression (Your Answers)
Two possible philosophies for using Huffman Compression:
What are some advantages/disadvantages of each idea? Which is better?
41
Huffman Compression (My Answers)
Two possible philosophies for using Huffman Compression:
What are some advantages/disadvantages of each idea? Which is better?
For very large inputs, the cost of including the codeword table will become insignificant.
42
Huffman Compression
Two possible philosophies for using Huffman Compression:
In practice, Philosophy 2 is used in the real world.
43
Huffman Compression Example [Demo Link]
Given input text: 我我刚刚刚是我是我刚李刚我李是爸李爸李是李我我李刚是我是刚爸是刚我爸我李是是李是我我刚爸是李我我我是爸我是我爸是我爸是我是刚我是爸刚爸我刚我我刚爸我我爸我刚爸爸李李李李我我爸李我我刚爸李我我李我爸我我
Step 1: Count frequencies.
Step 2: Build encoding array and decoding trie.
Step 3: Write decoding trie to output.huf.
Step 4: Write codeword for each symbol to output.huf.
Output bits: 010101010101001…00111111111101…
44
Decoding Trie
Codewords
我
爸
是
李
刚
0
1
0
1
1
0
0
1
0.35
0.17
0.17
0.16
0.15
Decoding Trie
See writeTrie in this code if you’re curious.
Huffman Decompression Example [Demo Link]
Given input bitstream: 010101010101001…00111111111101…
Step 1: Read in decoding trie.
Step 2: Use codeword bits to walk down the trie, outputting symbols every time you reach a leaf.
Output symbols: 我我刚刚刚是…
45
我
爸
是
李
刚
0
1
0
1
1
0
0
1
0.35
0.17
0.17
0.16
0.15
Decoding Trie
Codewords
Huffman Coding Summary
Given a file X.txt that we’d like to compress into X.huf:
To decompress X.huf:
46
See Huffman.java for an example implementation on 8-bit symbols.
Compression is Hard
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
47
Compression Algorithms (General)
The big idea in Huffman Coding is representing common symbols with small numbers of bits.
Many other approaches, e.g.
General idea: Exploit redundancy and existing order inside the sequence.
48
Compression Model #1: Algorithms Operating on Bits
So far in lecture, we’ve modeled compression as shown above.
Another useful model for compression (model #2) is as shown below:
49
01010101000001010101110...
Decompression
Algorithm C-1
1001010101...
C(B)
B
Interpreter
0111000001110101...
Some Program
B
0100001001001101...
Interesting Question #1
Given a bitstream, is there a limit to how much we can compress it?
50
Comparing Compression Algorithms
Different compression algorithms achieve different compression ratios on different files.
We’d like to try to compare them in some nice way.
Let’s start with a straightforward puzzle.
51
SuperZip: yellkey.com/attorney
Suppose an algorithm designer says their algorithm SuperZip can compress any bitstream by 50%. Why is this impossible?
52
Universal Compression: An Impossible Idea
Simplest argument: If true, they’d be able to compress any bitstream down to a single bit. Interpreter would have to be able to do the following (impossible) task for ANY output sequence.
53
01010101000001010101110
101010100001
111001
101
00
1
01010101000001010101110
101010100001
111001
Compression
Compression
Compression
101
Compression
00
1
Compression
Interesting Question #2
Are some bitstreams more compressible than others?
For example, which of these are more compressible?
54
A Sneaky Situation / Thought Experiment
Imagine a compression algorithm that has a special case:
55
010
001010100010101...
mobydick.txt
Compressed Bits
Decompression
Algorithm C-1
3 bits
5,771,240 bits
public static BitSet decompress(BitSet input, int inputLength) {
String inputBits = bitSetToString(input, inputLength);
if (inputBits.equals("010")) {
return stringToBitSet("001010100010101001010100011010000110010100…");
}
...
A Sneaky Situation / Thought Experiment
How can we change our “model” for the compression process to avoid this trickery?
56
010
001010100010101...
mobydick.txt
Compressed Bits
Decompression
Algorithm C-1
3 bits
5,771,240 bits
public static BitSet decompress(BitSet input, int inputLength) {
String inputBits = bitSetToString(input, inputLength);
if (inputBits.equals("010")) {
return stringToBitSet("001010100010101001010100011010000110010100");
}
...
5,771,548 bits
Compression Model #2
The fix: Let’s model the compressed data as including the source code for the decompression algorithm.
The nice thing with this approach: We have a universal algorithm (the interpreter) that does the decompression process.�
57
0111000001110101...
BitsAndAlgorithm.java
Interpreter
5,771,240 bits
0100001001001101...
5,771,551 bits
Compression Theory
In this more general framing for compression, we can ask the interesting question:
58
Interpreter
0111000001110101...
Some Program
Target Bitstream
0100001001001101...
Compression Theory
Suppose we want to find the shortest program that outputs a target bitstream X.
The theory behind compression is very deep. For example:
59
Interpreter
0111000001110101...
Some Program
Target Bitstream
0100001001001101...
Compression is Hard
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
60
At the Other Extreme
Yet some data is capable of extreme compression. Consider this video:
61
Compression
The video file of that Zoomed fractal is 5,973,182,440 bits long.
62
000000000000000001010010...
Java Interpreter acts as Decompression Algorithm C-1
0110100101101…
C(B)
B
Mandelbrot.java
mandelbrot.mp4
Mandelbrot
Here is the entire source for the code that generated the video we saw:
63
Fractals
In the 1970s, Benoit Mandelbrot built demonstrations that very short programs could generate highly complex visual patterns.
64
Music from Simple Rules
This notion of complexity from simple rules is arguably more interesting (and alarming) when applied towards sound generation.
In this clip, we can hear some fractal sounds.
See following two slides if you want to play around with this yourself.
65
Example Output
To experiment, you can use this basic sound playing tool: https://joshh.ug/61b/vsp/
To the right is is a typical sequence generated by one of these simple programs.
66
Music from Simple Rules
A couple of interesting programs:
67
+ (x = t * "6689"[t >> 16 & 3] / 24 & 127) * y / 4e4
+ ((t >> 8 ^ t >> 10 | t >> 14 | x) & 63)) % 1024; (link)
((t * ("36364689"[t >> 13 & 7] & 15)) / 12 & 128) +
(((((t >> 12) ^ (t >> 12) - 2) % 11 * t) / 4 | t >> 13) & 127)
) % 256; (link)
Compression Theory
Suppose we want to find the shortest program that outputs a target bitstream X.
The theory behind compression is very deep. For example:
68
LZW Style Compression (Extra)
Lecture 39, CS61B, Spring 2026
Today’s Goal: Compression
Prefix Free Codes
Shannon Fano Codes (Extra)
Huffman Coding
Compression Theory
LZW Style Compression (Extra)
69
Thought Experiment
How might we compress the following bitstreams (underlines for emphasis only)?
70
The LZW Approach
Key idea: Each codeword represents multiple symbols.
Demo Example: http://goo.gl/68Dncw
71
LZW
Named for inventors Limpel, Ziv, Welch.
Our version in lecture is simplified, for example:
72
LZW
Neat fact: You don’t have to send the codeword table along with the compressed bitstream.
LZW decompression example:
73