LSD radix sort variant that processes keys byte by byte from least significant to most significant.
Least Significant Byte sort is the byte oriented version of LSD radix sort. It processes fixed width keys one byte at a time, starting from the least significant byte and moving toward the most significant byte.
It relies on a stable inner sorting step, usually counting sort with 256 buckets.
Problem
Given an array of fixed width integer keys, sort the array in increasing order.
Each key can be written as:
where each is a byte:
Idea
Sort the array by byte positions in increasing order of significance:
After each pass, the array is sorted by the processed suffix of bytes.
Algorithm
lsb_sort(A, bytes):
for p from 0 to bytes - 1:
stable_counting_sort_by_byte(A, p)
return AByte extraction:
Example
Sort:
Byte form:
| value | high byte | low byte |
|---|---|---|
| 513 | 2 | 1 |
| 256 | 1 | 0 |
| 258 | 1 | 2 |
| 1 | 0 | 1 |
After sorting by low byte:
After sorting by high byte:
Correctness
After processing byte , the array is sorted by the suffix:
The base case holds after sorting by . For the inductive step, stable sorting by orders elements by the new byte while preserving the ordering of lower bytes.
After all bytes have been processed, the array is sorted by the full key.
Complexity
Let:
- be number of elements
- be number of bytes
Each pass costs:
Total time:
Space:
For fixed width integers, is constant, so time is linear in .
Properties
| property | value |
|---|---|
| stable | yes |
| in place | no |
| comparison based | no |
| direction | LSD |
| radix | 256 |
When to Use
Use LSB sort when:
- sorting large arrays of fixed width integers
- stability is required
- byte extraction is cheap
- auxiliary memory is acceptable
Avoid when:
- memory must be minimal
- keys are variable length
- recursive MSD methods perform better on the dataset
Implementation
def lsb_sort(a):
if not a:
return a
max_bits = max(a).bit_length()
bytes_count = (max_bits + 7) // 8
for p in range(bytes_count):
count = [0] * 256
for x in a:
b = (x >> (8 * p)) & 255
count[b] += 1
for i in range(1, 256):
count[i] += count[i - 1]
out = [0] * len(a)
for i in range(len(a) - 1, -1, -1):
x = a[i]
b = (x >> (8 * p)) & 255
count[b] -= 1
out[count[b]] = x
a = out
return a