Radix Sorts
1
Lecture 36 (Sorting 5)
CS61B, Spring 2025 @ UC Berkeley
Slides credit: Josh Hug
Sorting Stability
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts
Sorting Summary (so far)
Listed by mechanism:
Listed by memory and runtime:
| Memory | # Compares | Notes |
Heapsort | Θ(1) | Θ(N log N) worst | Bad caching (61C) |
Insertion | Θ(1) | Θ(N2) worst | Θ(N) if almost sorted |
Mergesort | Θ(N) | Θ(N log N) worst | |
Random Quicksort | Θ(log N) (call stack) | Θ(N log N) expected | Fastest sort |
Other Desirable Sorting Properties: Stability
A sort is said to be stable if order of equivalent items is preserved.
Bas | 3 |
Fikriyya | 4 |
Jana | 3 |
Jouni | 3 |
Lara | 1 |
Nikolaj | 4 |
Rosella | 3 |
Sigurd | 2 |
sort(studentRecords, BY_NAME);
Lara | 1 |
Sigurd | 2 |
Bas | 3 |
Jana | 3 |
Jouni | 3 |
Rosella | 3 |
Fikriyya | 4 |
Nikolaj | 4 |
sort(studentRecords, BY_SECTION);
Equivalent items don’t ‘cross over’ when being stably sorted.
Other Desirable Sorting Properties: Stability
A sort is said to be stable if order of equivalent items is preserved.
Bas | 3 |
Fikriyya | 4 |
Jana | 3 |
Jouni | 3 |
Lara | 1 |
Nikolaj | 4 |
Rosella | 3 |
Sigurd | 2 |
sort(studentRecords, BY_NAME);
Lara | 1 |
Sigurd | 2 |
Jouni | 3 |
Rosella | 3 |
Bas | 3 |
Jana | 3 |
Fikriyya | 4 |
Nikolaj | 4 |
sort(studentRecords, BY_SECTION);
Sorting instability can be really annoying! Wanted students listed alphabetically by section.
Sorting Stability
Is insertion sort stable?
Is Quicksort stable?
S O R T E X A M P L E
S O R T E X A M P L E (0 swaps)
O S R T E X A M P L E (1 swap )
O R S T E X A M P L E (1 swap )
O R S T E X A M P L E (0 swaps)
E O R S T X A M P L E (4 swaps)
E O R S T X A M P L E (0 swaps)
A E O R S T X M P L E (6 swaps)
A E M O R S T X P L E (5 swaps)
A E M O P R S T X L E (4 swaps)
A E L M O P R S T X E (7 swaps)
A E E L M O P R S T X (8 swaps)
6
8
3
1
2
7
4
Sorting Stability
Is insertion sort stable?
Is Quicksort stable?
S O R T E X A M P L E
S O R T E X A M P L E (0 swaps)
O S R T E X A M P L E (1 swap )
O R S T E X A M P L E (1 swap )
O R S T E X A M P L E (0 swaps)
E O R S T X A M P L E (4 swaps)
E O R S T X A M P L E (0 swaps)
A E O R S T X M P L E (6 swaps)
A E M O R S T X P L E (5 swaps)
A E M O P R S T X L E (4 swaps)
A E L M O P R S T X E (7 swaps)
A E E L M O P R S T X (8 swaps)
6
7
3
1
2
8
3
2
3
3
1
6
8
7
3
1
2
3
6
7
8
Hoare partitioning.
Three array partitioning.
Stability
| Memory | # Compares | Notes | Stable? |
Heapsort | Θ(1) | Θ(N log N) | Bad caching (61C) | No |
Insertion | Θ(1) | Θ(N2) | Θ(N) if almost sorted | Yes |
Mergesort | Θ(N) | Θ(N log N) | | Yes |
Quicksort LTHS | Θ(log N) | Θ(N log N) expected | Fastest sort | No |
You can create a stable Quicksort (i.e. the version from the previous lecture). However, unstable partitioning schemes (like Hoare partitioning) tend to be faster. All reasonable partitioning schemes yield Θ(N log N) expected runtime, but with different constants.
This is due to the cost of tracking recursive calls by the computer, and is also an “expected” amount. The difference between log N and constant memory is trivial.
Arrays.sort
In Java, Arrays.sort(someArray) uses:
Why? See A level problems.
Arrays.sort
In Java, Arrays.sort(someArray) uses:
Why?
Arrays.sort
In Java, Arrays.sort(someArray) uses:
Why?
Optimizing Sorts
Additional tricks we can play:
Today’s Two New Ideas
Today we’ll cover two new ideas:
Warmup: Digit-by-digit Sorting
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
… |
|
|
|
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
What are the 4 integers at the end of the array?
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
… |
|
|
|
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
I put 53 and 23 in this order. Would they always be in this order?
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
I put 53 and 23 in this order. Would they always be in this order?
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
12 |
12 |
13 |
22 |
23 |
?? |
?? |
?? |
?? |
41 |
41 |
42 |
In what order will 31,
32, 34, and 34 appear?
Digit-by-digit Sorting
As a warmup to the later part of today’s lecture. Suppose we have a list of integers we want to sort.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
12 |
12 |
13 |
22 |
23 |
31 |
32 |
34 |
34 |
41 |
41 |
42 |
Digit-by-digit Sorting
This procedure does not work if the sort subroutine is unstable.
41 |
41 |
31 |
32 |
22 |
12 |
12 |
42 |
53 |
23 |
34 |
34 |
22 |
34 |
41 |
53 |
23 |
41 |
32 |
34 |
12 |
31 |
12 |
42 |
12 |
12 |
13 |
22 |
23 |
34 |
32 |
31 |
34 |
41 |
41 |
42 |
Digit-by-digit Sorting
Example of a digit-by-digit sort:
322 |
434 |
141 |
353 |
223 |
341 |
432 |
234 |
112 |
331 |
412 |
342 |
141 |
341 |
331 |
322 |
432 |
112 |
412 |
342 |
353 |
223 |
434 |
234 |
112 |
412 |
322 |
223 |
331 |
432 |
434 |
234 |
141 |
341 |
342 |
353 |
112 |
141 |
223 |
234 |
322 |
331 |
341 |
342 |
353 |
412 |
432 |
434 |
Last digit is 3
Mid digit is 3
Top digit is 3
Digit-by-digit Sorting
Two quick notes:
322 |
434 |
141 |
353 |
223 |
341 |
432 |
234 |
112 |
331 |
412 |
342 |
141 |
341 |
331 |
322 |
432 |
112 |
412 |
342 |
353 |
223 |
434 |
234 |
112 |
412 |
322 |
223 |
331 |
432 |
434 |
234 |
141 |
341 |
342 |
353 |
112 |
141 |
223 |
234 |
322 |
331 |
341 |
342 |
353 |
412 |
432 |
434 |
Last digit is 3
Mid digit is 3
Top digit is 3
We’ll come back to digit-by-digit sorting later!
The Counting Sort Algorithm
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts:
Comparison Based Sorting
The key idea from our previous sorting lecture: Sorting requires Ω(N log N) compares in the worst case.
From an asymptotic perspective, that means no matter how clever we are, we can never beat Merge Sort’s worst case runtime of Θ(N log N).
Example #1: Sleep Sort (for Sorting Integers) (not actually good)
For each integer x in array A, start a new program that:
All start at the same time.
Runtime:
Invented by 4chan (?).
The catch: On real machines, scheduling execution of programs must be done by an operating system. In practice requires list of running programs sorted by sleep time.
Example #2: Counting Sort: Exploiting Space Instead of Time
Assuming keys are unique integers 0 to 11.
Idea:
# | | | |
5 | Sandra | Vanilla | Grimes |
0 | Lauren | Mint | Jon Talabot |
11 | Lisa | Vanilla | Blue Peter |
9 | Dave | Chocolate | Superpope |
4 | JS | Fish | The Filthy Reds |
7 | James | Rocky Road | Robots are Supreme |
3 | Edith | Vanilla | My Bloody Valentine |
6 | Swimp | Chocolate | Sef |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
8 | Lee | Vanilla | La(r)va |
10 | Bearman | Butter Pecan | Extrobophile |
Example #2: Counting Sort: Exploiting Space Instead of Time
# | | | |
5 | Sandra | Vanilla | Grimes |
0 | Lauren | Mint | Jon Talabot |
11 | Lisa | Vanilla | Blue Peter |
9 | Dave | Chocolate | Superpope |
4 | JS | Fish | The Filthy Reds |
7 | James | Rocky Road | Robots are Supreme |
3 | Edith | Vanilla | My Bloody Valentine |
6 | Swimp | Chocolate | Sef |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
8 | Lee | Vanilla | La(r)va |
10 | Bearman | Butter Pecan | Extrobophile |
# | | | |
| | | |
| | | |
| | | |
| | | |
| | | |
5 | Sandra | Vanilla | Grimes |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
Example #2: Counting Sort: Exploiting Space Instead of Time
# | | | |
5 | Sandra | Vanilla | Grimes |
0 | Lauren | Mint | Jon Talabot |
11 | Lisa | Vanilla | Blue Peter |
9 | Dave | Chocolate | Superpope |
4 | JS | Fish | The Filthy Reds |
7 | James | Rocky Road | Robots are Supreme |
3 | Edith | Vanilla | My Bloody Valentine |
6 | Swimp | Chocolate | Sef |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
8 | Lee | Vanilla | La(r)va |
10 | Bearman | Butter Pecan | Extrobophile |
# | | | |
0 | Lauren | Mint | Jon Talabot |
| | | |
| | | |
| | | |
| | | |
5 | Sandra | Vanilla | Grimes |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
Example #2: Counting Sort: Exploiting Space Instead of Time
# | | | |
5 | Sandra | Vanilla | Grimes |
0 | Lauren | Mint | Jon Talabot |
11 | Lisa | Vanilla | Blue Peter |
9 | Dave | Chocolate | Superpope |
4 | JS | Fish | The Filthy Reds |
7 | James | Rocky Road | Robots are Supreme |
3 | Edith | Vanilla | My Bloody Valentine |
6 | Swimp | Chocolate | Sef |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
8 | Lee | Vanilla | La(r)va |
10 | Bearman | Butter Pecan | Extrobophile |
# | | | |
0 | Lauren | Mint | Jon Talabot |
| | | |
| | | |
| | | |
| | | |
5 | Sandra | Vanilla | Grimes |
| | | |
| | | |
| | | |
| | | |
| | | |
11 | Lisa | Vanilla | Blue Peter |
Example #2: Counting Sort: Exploiting Space Instead of Time
# | | | |
5 | Sandra | Vanilla | Grimes |
0 | Lauren | Mint | Jon Talabot |
11 | Lisa | Vanilla | Blue Peter |
9 | Dave | Chocolate | Superpope |
4 | JS | Fish | The Filthy Reds |
7 | James | Rocky Road | Robots are Supreme |
3 | Edith | Vanilla | My Bloody Valentine |
6 | Swimp | Chocolate | Sef |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
8 | Lee | Vanilla | La(r)va |
10 | Bearman | Butter Pecan | Extrobophile |
# | | | |
0 | Lauren | Mint | Jon Talabot |
1 | Delbert | Strawberry | Ronald Jenkees |
2 | Glaser | Cardamom | Rx Nightly |
3 | Edith | Vanilla | My Bloody Valentine |
4 | JS | Fish | The Filthy Reds |
5 | Sandra | Vanilla | Grimes |
6 | Swimp | Chocolate | Sef |
7 | James | Rocky Road | Robots are Supreme |
8 | Lee | Vanilla | La(r)va |
9 | Dave | Chocolate | Superpope |
10 | Bearman | Butter Pecan | Extrobophile |
11 | Lisa | Vanilla | Blue Peter |
Generalizing Counting Sort
We just sorted N items in Θ(N) worst case time.
Simplest case:
More complex cases:
Counting Sort
Alphabet case: Keys belong to a finite ordered alphabet.
Question: What will be the index of the first ♥?
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Alphabet case: Keys belong to a finite ordered alphabet.
Question: What will be the index of the first ♥?
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | |
♣️ | |
♣️ | |
♠ | |
♠ | |
| |
| |
| |
| |
| |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Implementing Counting Sort with Counting Arrays
Counting sort:
Bottom line, we can use counting sort to sort N objects in Θ(N) time.
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
0
1
2
3
Counts
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 0 |
♠ | 3 |
♥️ | 5 |
♦️ | 9 |
0
1
2
3
0
1
2
3
Counts
Starting Points
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 0 |
♠ | 3 |
♥️ | 5 |
♦️ | 9 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 0 |
♠ | 4 |
♥️ | 5 |
♦️ | 9 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
| |
| |
| |
♠ | Lauren |
| |
| |
| |
| |
| |
| |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 0 |
♠ | 4 |
♥️ | 6 |
♦️ | 9 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
| |
| |
| |
♠ | Lauren |
| |
♥️ | Delbert |
| |
| |
| |
| |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 0 |
♠ | 4 |
♥️ | 6 |
♦️ | 10 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
| |
| |
| |
♠ | Lauren |
| |
♥️ | Delbert |
| |
| |
| |
♦️ | Glaser |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 1 |
♠ | 4 |
♥️ | 6 |
♦️ | 10 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
| |
| |
♠ | Lauren |
| |
♥️ | Delbert |
| |
| |
| |
♦️ | Glaser |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 1 |
♠ | 5 |
♥️ | 6 |
♦️ | 10 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
| |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
| |
| |
| |
♦️ | Glaser |
| |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 1 |
♠ | 5 |
♥️ | 6 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
| |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
| |
| |
| |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 1 |
♠ | 5 |
♥️ | 7 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
| |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
| |
| |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 1 |
♠ | 5 |
♥️ | 8 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
| |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
♥️ | James |
| |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 2 |
♠ | 5 |
♥️ | 8 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
♣️ | Lee |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
♥️ | James |
| |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 2 |
♠ | 5 |
♥️ | 9 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
♣️ | Lee |
| |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
♥️ | James |
♥️ | Dave |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 3 |
♠ | 5 |
♥️ | 9 |
♦️ | 11 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
♣️ | Lee |
♣️ | Bearman |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
♥️ | James |
♥️ | Dave |
♦️ | Glaser |
♦️ | Sandra |
| |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort
Example:
| |
♠ | Lauren |
♥️ | Delbert |
♦️ | Glaser |
♣️ | Edith |
♠ | JS |
♦️ | Sandra |
♥️ | Swimp |
♥️ | James |
♣️ | Lee |
♥️ | Dave |
♣️ | Bearman |
♦️ | Lisa |
| |
♣️ | 3 |
♠ | 2 |
♥️ | 4 |
♦️ | 3 |
| |
♣️ | 3 |
♠ | 5 |
♥️ | 9 |
♦️ | 12 |
0
1
2
3
0
1
2
3
Counts
Starting Points
| |
♣️ | Edith |
♣️ | Lee |
♣️ | Bearman |
♠ | Lauren |
♠ | JS |
♥️ | Delbert |
♥️ | Swimp |
♥️ | James |
♥️ | Dave |
♦️ | Glaser |
♦️ | Sandra |
♦️ | Lisa |
0
1
2
3
4
5
6
7
8
9
10
11
Sorted
Counting Sort Runtime
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts:
Counting Sort vs. Quicksort
For sorting an array of the 100 largest cities by population, which sort do you think has a better expected worst case runtime in seconds?
First question to ask yourself: What is the alphabet for counting sort here?
Counting Sort vs. Quicksort
For sorting an array of the 100 largest cities by population, which sort do you think has a better expected worst case runtime in seconds?
Counting sort requires building an array of size 37,832,892 (population of Tokyo).
| |
6352254 | Ahmedabad |
4778000 | Alexandria |
5346518 | Ankara |
6555956 | Atlanta |
8495928 | Bandung |
12517749 | Bangalore |
... | ... |
... | ... |
4777999 | 0 |
4778000 | 1 |
4778001 | 0 |
4778002 | 0 |
... | ... |
37832892 | 1 |
Counts
...
Counting Sort Runtime Analysis
What is the runtime for counting sort on N keys with alphabet of size R?
Counting Sort Runtime Analysis
Total runtime on N keys with alphabet of size R: Θ(N+R)
Memory usage: Θ(N+R)
Bottom line: If N is ≥ R, then we expect reasonable performance.
Empirical experiments needed to compare vs. Quicksort on practical inputs.
For ordered array.
For counts and starting points.
See hidden slide after this for a more verbose explanation.
Counting Sort Runtime Analysis (More Verbose)
Total runtime on N keys with alphabet of size R: Θ(N+R)
Memory usage: Θ(N+R)
Bottom line: If N is ≥ R, then we expect reasonable performance.
Empirical experiments needed to compare vs. Quicksort on practical inputs.
For ordered array.
For counts and starting points.
Counting Sort vs. Quicksort
Give an example of a specific situation where Counting Sort will be clearly faster than Quicksort.
Previous example was sorting N = 100 cities by population (R = 37,832,892).
Sort Summary
Counting sort is nice, but alphabetic restriction limits usefulness.
N: Number of keys. R: Size of alphabet.
| Memory | Runtime | Notes | Stable? |
Heapsort | Θ(1) | Θ(N log N) | Bad caching (61C) | No |
Insertion | Θ(1) | Θ(N2) | Small N, almost sorted | Yes |
Mergesort | Θ(N) | Θ(N log N) | Fastest stable | Yes |
Random Quicksort | Θ(log N) | Θ(N log N) expected | Fastest compare sort | No |
Counting Sort | Θ(N+R) | Θ(N+R) | Alphabet keys only | Yes |
LSD Radix Sort
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts
Radix Sort
Counting sort is slow when the alphabet is large.
| |
♠♠ | Lauren |
♥️♦️ | Delbert |
♦️♣️ | Glaser |
♣️♥️ | Edith |
♠♥️ | JS |
♦️♣️ | Sandra |
♥️♠ | Swimp |
♥️♦️ | James |
♣️♠ | Lee |
♥️♣️ | Dave |
♣️♠ | Bearman |
♦️♠ | Lisa |
| |
horse | Lauren |
elf | Delbert |
cat | Glaser |
crab | Edith |
monkey | JS |
rhino | Sandra |
raccoon | Swimp |
cat | James |
fish | Lee |
tree | Dave |
virus | Bearman |
human | Lisa |
| |
4238 | Lauren |
34163 | Delbert |
123 | Glaser |
43415 | Edith |
9918 | JS |
767 | Sandra |
3 | Swimp |
634 | James |
724 | Lee |
2346 | Dave |
457 | Bearman |
312 | Lisa |
Digit-by-digit Counting Sort
As we’ve seen, we can sort each digit independently from rightmost digit towards left.
| |
♠♠ | Lauren |
♥️♦️ | Delbert |
♦️♣️ | Glaser |
♣️♥️ | Edith |
♠♥️ | JS |
♦️♣️ | Sandra |
♥️♠ | Swimp |
♥️♦️ | James |
♣️♠ | Lee |
♥️♣️ | Dave |
♣️♠ | Bearman |
♦️♠ | Lisa |
| |
♦️♣️ | Glaser |
♦️♣️ | Sandra |
♥️♣️ | Dave |
♠♠ | Lauren |
♥️♠ | Swimp |
♣️♠ | Lee |
♣️♠ | Bearman |
♦️♠ | Lisa |
♣️♥️ | Edith |
♠♥️ | JS |
♥️♦️ | Delbert |
♥️♦️ | James |
| |
♣️♠ | Lee |
♣️♠ | Bearman |
♣️♥️ | Edith |
♠♠ | Lauren |
♠♥️ | JS |
♥️♣️ | Dave |
♥️♠ | Swimp |
♥️♦️ | Delbert |
♥️♦️ | James |
♦️♣️ | Glaser |
♦️♣️ | Sandra |
♦️♠ | Lisa |
Digit-by-digit Counting Sort
Sort each digit independently from rightmost digit towards left.
| |
22 | Lauren |
34 | Delbert |
41 | Glaser |
13 | Edith |
23 | JS |
41 | Sandra |
32 | Swimp |
34 | James |
12 | Lee |
31 | Dave |
12 | Bearman |
42 | Lisa |
| |
41 | Glaser |
41 | Sandra |
31 | Dave |
22 | Lauren |
32 | Swimp |
12 | Lee |
12 | Bearman |
42 | Lisa |
13 | Edith |
23 | JS |
34 | Delbert |
34 | James |
| |
12 | Lee |
12 | Bearman |
13 | Edith |
22 | Lauren |
23 | JS |
31 | Dave |
32 | Swimp |
34 | Delbert |
34 | James |
41 | Glaser |
41 | Sandra |
42 | Lisa |
LSD Radix Sort
Non-comparison based sorting algorithms that proceed digit-by-digit are called “Radix Sorts”.
Via wikipedia: “In a positional numeral system, the radix or base is the number of unique digits, including the digit zero, used to represent numbers.”
The sort we’ve just discussed is called “LSD Radix Sort”.
LSD Runtime
What is the runtime of LSD sort?
| |
22 | Lauren |
34 | Delbert |
41 | Glaser |
13 | Edith |
23 | JS |
41 | Sandra |
32 | Swimp |
34 | James |
12 | Lee |
31 | Dave |
12 | Bearman |
42 | Lisa |
| |
41 | Glaser |
41 | Sandra |
31 | Dave |
22 | Lauren |
32 | Swimp |
12 | Lee |
12 | Bearman |
42 | Lisa |
13 | Edith |
23 | JS |
34 | Delbert |
34 | James |
| |
12 | Lee |
12 | Bearman |
13 | Edith |
22 | Lauren |
23 | JS |
31 | Dave |
32 | Swimp |
34 | Delbert |
34 | James |
41 | Glaser |
41 | Sandra |
42 | Lisa |
LSD Runtime
What is the runtime of LSD sort?
| |
22 | Lauren |
34 | Delbert |
41 | Glaser |
13 | Edith |
23 | JS |
41 | Sandra |
32 | Swimp |
34 | James |
12 | Lee |
31 | Dave |
12 | Bearman |
42 | Lisa |
| |
41 | Glaser |
41 | Sandra |
31 | Dave |
22 | Lauren |
32 | Swimp |
12 | Lee |
12 | Bearman |
42 | Lisa |
13 | Edith |
23 | JS |
34 | Delbert |
34 | James |
| |
12 | Lee |
12 | Bearman |
13 | Edith |
22 | Lauren |
23 | JS |
31 | Dave |
32 | Swimp |
34 | Delbert |
34 | James |
41 | Glaser |
41 | Sandra |
42 | Lisa |
Non-equal Key Lengths
After processing least significant digit, we have array shown below. Now what?
43 |
9 |
817 |
412 |
51 |
33 |
71 |
51 |
71 |
412 |
43 |
33 |
817 |
9 |
Non-equal Key Lengths
When keys are of different lengths, can treat empty spaces as less than all other characters.
·43 |
··9 |
817 |
412 |
·51 |
·33 |
·71 |
·51 |
·71 |
412 |
·43 |
·33 |
817 |
··9 |
··9 |
412 |
817 |
·33 |
·43 |
·51 |
·71 |
··9 |
·33 |
·43 |
·51 |
·71 |
412 |
817 |
Sorting Summary
W passes of counting sort: Θ(WN+WR) runtime.
N: Number of keys. R: Size of alphabet. W: Width of longest key.
*: Assumes constant compareTo time.
| Memory | Runtime | Notes | Stable? |
Heapsort | Θ(1) | Θ(N log N)* | Bad caching (61C) | No |
Insertion | Θ(1) | Θ(N2)* | Small N, almost sorted | Yes |
Mergesort | Θ(N) | Θ(N log N)* | Fastest stable sort | Yes |
Random Quicksort | Θ(log N) | Θ(N log N)* expected | Fastest compare sort | No |
Counting Sort | Θ(N+R) | Θ(N+R) | Alphabet keys only | Yes |
LSD Sort | Θ(N+R) | Θ(WN+WR) | Strings of alphabetical keys only | Yes |
MSD Radix Sort
Lecture 36, CS61B, Spring 2025
Sorting Stability
Warmup: Digit-by-digit Sorting
Counting Sort
Radix Sorts
MSD (Most Significant Digit) Radix Sort
Basic idea: Just like LSD, but sort from leftmost digit towards the right.
Pseudopseudohypoparathyroidism |
Floccinaucinihilipilification |
Antidisestablishmentarianism |
Honorificabilitudinitatibus |
Pneumonoultramicroscopicsilicovolcanoconiosis |
MSD Sort Question
Suppose we sort by topmost digit, then middle digit, then rightmost digit. Will we arrive at the correct result? A. Yes, B. No
a | d | d |
c | a | b |
f | a | d |
f | e | e |
b | a | d |
b | e | e |
f | e | d |
b | e | d |
a | c | e |
a | d | d |
a | c | e |
b | a | d |
b | e | e |
b | e | d |
c | a | b |
f | a | d |
f | e | e |
f | e | d |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
MSD Sort Question
Suppose we sort by topmost digit, then middle digit, then rightmost digit. Will we arrive at the correct result? A. Yes, B. No. How do we fix?
a | d | d |
c | a | b |
f | a | d |
f | e | e |
b | a | d |
b | e | e |
f | e | d |
b | e | d |
a | c | e |
a | d | d |
a | c | e |
b | a | d |
b | e | e |
b | e | d |
c | a | b |
f | a | d |
f | e | e |
f | e | d |
b | a | d |
| | |
| | |
| | |
| | |
a | d | d |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
MSD Radix Sort (correct edition)
Key idea: Sort each subproblem separately.
a | d | d |
c | a | b |
f | a | d |
f | e | e |
b | a | d |
b | e | e |
f | e | d |
b | e | d |
a | c | e |
f | a | d |
f | e | e |
f | e | d |
a | d | d |
a | c | e |
b | a | d |
b | e | e |
b | e | d |
c | a | b |
a | c | e |
b | a | d |
f | e | e |
f | e | d |
a | d | d |
b | e | e |
b | e | d |
f | a | d |
b | e | d |
b | e | e |
f | e | d |
f | e | e |
Runtime of MSD
What is the Best Case of MSD sort (in terms of N, W, R)?
What is the Worst Case of MSD sort (in terms of N, W, R)?
Runtime of MSD
Best Case.
Worst Case.
Sorting Runtime Analysis
N: Number of keys. R: Size of alphabet. W: Width of longest key.
*: Assumes constant compareTo time.
| Memory | Runtime (worst) | Notes | Stable? |
Heapsort | Θ(1) | Θ(N log N)* | Bad caching (61C) | No |
Insertion | Θ(1) | Θ(N2)* | Fastest for small N, almost sorted data | Yes |
Mergesort | Θ(N) | Θ(N log N)* | Fastest stable sort | Yes |
Random Quicksort | Θ(log N) | Θ(N log N)* expected | Fastest compare sort | No |
Counting Sort | Θ(N+R) | Θ(N+R) | Alphabet keys only | Yes |
LSD Sort | Θ(N+R) | Θ(WN+WR) | Strings of alphabetical keys only | Yes |
MSD Sort | Θ(N+WR) | Θ(N+R) (best) Θ(WN+WR) (worst) | Bad caching (61C) | Yes |
Sounds of Sorting Algorithms
Starts with selection sort: https://www.youtube.com/watch?v=kPRA0W1kECg
Insertion sort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=0m9s
Quicksort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=0m38s
Mergesort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=1m05s
Heapsort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=1m28s
LSD sort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=1m54s
MSD sort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=2m10s
Shell’s sort: https://www.youtube.com/watch?v=kPRA0W1kECg&t=3m37s
Questions to ponder (later… after class):