Radix Sort
A non-comparison based sorting algorithm that sorts numbers digit by digit, starting from the least significant digit to the most significant digit.
Algorithm Information
Time Complexity
O(d × n)O(d × n)O(d × n)Space Complexity
O(n + k)Properties
Algorithm Code
1function radixSort(arr) {2 // Find the maximum number to know number of digits3 const max = Math.max(...arr);4 5 // Do counting sort for every digit6 for (let exp = 1; Math.floor(max / exp) > 0; exp *= 10) {7 countingSort(arr, exp);8 }9 10 return arr;11}12 13function countingSort(arr, exp) {14 const n = arr.length;15 const output = new Array(n);16 const count = new Array(10).fill(0);17 18 // Store count of occurrences of each digit19 for (let i = 0; i < n; i++) {20 const digit = Math.floor(arr[i] / exp) % 10;21 count[digit]++;22 }23 24 // Change count[i] so it contains actual position25 for (let i = 1; i < 10; i++) {26 count[i] += count[i - 1];27 }28 29 // Build the output array30 for (let i = n - 1; i >= 0; i--) {31 const digit = Math.floor(arr[i] / exp) % 10;32 output[count[digit] - 1] = arr[i];33 count[digit]--;34 }35 36 // Copy the output array to arr37 for (let i = 0; i < n; i++) {38 arr[i] = output[i];39 }40}Variable State
Call Stack
Array Visualization
Watch how Radix Sort processes each digit position from least to most significant
Statistics
Legend
Starting Radix Sort. Maximum number is 802, which determines the number of passes needed.
How Radix Sort Works
Discover the power of non-comparison sorting through digit-by-digit processing and bucket distribution.
Algorithm Overview
Radix Sort is a non-comparison based sorting algorithm that sorts numbers by processing individual digits. It works by distributing elements into buckets based on each digit's value, starting from the least significant digit and moving to the most significant digit.
🪣 Bucket Distribution Strategy
Unlike comparison-based algorithms, radix sort never compares elements directly. Instead, it uses the counting sort algorithm as a subroutine to sort by each digit position. This approach can achieve linear time complexity for fixed-width integers.
Step-by-Step Process
Find Maximum Number
Determine the maximum number in the array to know how many digits we need to process. This determines the number of passes required.
const numDigits = Math.floor(Math.log10(max)) + 1;
Process Each Digit Position
Starting from the least significant digit (rightmost), use counting sort to sort the array based on the current digit position.
countingSort(arr, exp);
}
Count Digit Occurrences
For the current digit position, count how many numbers have each digit (0-9). This creates a frequency distribution.
Reconstruct Array
Use the counting information to place elements in their correct positions, maintaining stability by processing from right to left.
for (let i = n - 1; i >= 0; i--) {
const digit = Math.floor(arr[i] / exp) % 10;
output[count[digit] - 1] = arr[i];
count[digit]--;
}
Radix Sort in Action
Here's how radix sort processes an example with 3-digit numbers:
🔄 Stability Preservation
Radix sort maintains stability by processing elements from right to left when reconstructing the array. This ensures that elements with the same digit value maintain their relative order from previous passes.
Complete Implementation
Here's the complete radix sort implementation with counting sort subroutine:
function radixSort(arr) {
// Find the maximum number to know number of digits
const max = Math.max(...arr);
// Do counting sort for every digit
// exp is 10^i where i is current digit number
for (let exp = 1; Math.floor(max / exp) > 0; exp *= 10) {
countingSort(arr, exp);
}
return arr;
}
function countingSort(arr, exp) {
const n = arr.length;
const output = new Array(n); // Output array
const count = new Array(10).fill(0); // Count array for digits 0-9
// Store count of occurrences of each digit
for (let i = 0; i < n; i++) {
const digit = Math.floor(arr[i] / exp) % 10;
count[digit]++;
}
// Change count[i] so that it contains actual position
// of this digit in output[]
for (let i = 1; i < 10; i++) {
count[i] += count[i - 1];
}
// Build the output array
// Process from right to left to maintain stability
for (let i = n - 1; i >= 0; i--) {
const digit = Math.floor(arr[i] / exp) % 10;
output[count[digit] - 1] = arr[i];
count[digit]--;
}
// Copy the output array to arr[], so that arr[] now
// contains sorted numbers according to current digit
for (let i = 0; i < n; i++) {
arr[i] = output[i];
}
}
// Optimized version for different bases
function radixSortBase(arr, base = 10) {
const max = Math.max(...arr);
for (let exp = 1; Math.floor(max / exp) > 0; exp *= base) {
countingSortBase(arr, exp, base);
}
return arr;
}
function countingSortBase(arr, exp, base) {
const n = arr.length;
const output = new Array(n);
const count = new Array(base).fill(0);
// Count occurrences of each digit in given base
for (let i = 0; i < n; i++) {
const digit = Math.floor(arr[i] / exp) % base;
count[digit]++;
}
// Convert counts to positions
for (let i = 1; i < base; i++) {
count[i] += count[i - 1];
}
// Build output array (stable)
for (let i = n - 1; i >= 0; i--) {
const digit = Math.floor(arr[i] / exp) % base;
output[count[digit] - 1] = arr[i];
count[digit]--;
}
// Copy back to original array
for (let i = 0; i < n; i++) {
arr[i] = output[i];
}
}
// Example usage:
const numbers = [170, 45, 75, 90, 2, 802, 24, 66];
console.log("Original:", numbers);
radixSort(numbers);
console.log("Sorted:", numbers);Key Concepts & Characteristics
✅ Advantages
- •Linear time complexity: O(d×n) where d is number of digits
- •Stable sorting: Maintains relative order of equal elements
- •Non-comparison based: Doesn't rely on element comparisons
- •Predictable performance: Consistent behavior regardless of input order
- •Parallelizable: Digit processing can be parallelized
❌ Disadvantages
- •Limited to integers: Only works with fixed-width integer keys
- •Extra memory: Requires O(n + k) additional space
- •Digit dependency: Performance depends on number of digits
- •Cache performance: Non-sequential memory access patterns
- •Not general-purpose: Cannot sort arbitrary comparable objects
🚀 Linear Time Achievement
Radix sort achieves linear time complexity by avoiding comparisons entirely. For fixed-width integers (constant d), it runs in O(n) time, breaking the O(n log n) lower bound that applies to comparison-based sorting algorithms.
Complexity Analysis
Best Case
Linear time when d (number of digits) is constant or small relative to n.
Average Case
Consistent performance regardless of input distribution.
Worst Case
Even worst-case input maintains linear time complexity.
Detailed Analysis
Variants and Optimizations
Algorithm Variants
- •LSD Radix Sort: Least Significant Digit first (most common)Processes digits from right to left, suitable for fixed-width integers
- •MSD Radix Sort: Most Significant Digit firstProcesses digits from left to right, can stop early for strings
- •Binary Radix Sort: Uses base-2 instead of base-10More cache-friendly, processes one bit at a time
Performance Optimizations
- •Variable Base: Use larger bases (e.g., 256) for fewer passesTrades memory for speed, reduces number of passes
- •Hybrid Approach: Switch to comparison sort for small subarraysUsed in MSD radix sort when partitions become small
- •In-place Variants: Reduce space complexityMore complex but uses less memory
When to Use Radix Sort
✅ Perfect for:
- • Integer sorting: Fixed-width integers, IDs, timestamps
- • Large datasets: When n is much larger than d (number of digits)
- • Stable sorting required: Maintains relative order of equal elements
- • String sorting: Fixed-length strings (MSD variant)
- • Counting applications: When you need to count occurrences
- • Parallel processing: Easy to parallelize digit processing
❌ Avoid for:
- • Floating-point numbers: Requires special handling
- • Variable-length data: Strings of different lengths
- • Memory-constrained systems: Requires O(n + k) extra space
- • Small datasets: Overhead may not be worth it
- • Many digits: When d approaches or exceeds log n
- • General objects: Cannot sort arbitrary comparable objects
🎯 Sweet Spot
Radix sort excels when sorting large arrays of integers where the number of digits is small relative to the array size. For example, sorting millions of 32-bit integers (d=10) is much faster with radix sort than comparison-based algorithms.
Real-World Applications
Common Use Cases
- • Database indexing: Sorting large tables by integer keys
- • IP address sorting: Network routing and analysis
- • Timestamp sorting: Log file processing and analysis
- • ID sorting: User IDs, product codes, transaction IDs
- • Suffix arrays: String processing and pattern matching
- • Bucket sort implementation: As a subroutine for distribution
Industry Examples
- • MapReduce: Distributed sorting of large datasets
- • Graphics processing: Sorting pixels by color values
- • Financial systems: Transaction processing by timestamp
- • Telecommunications: Call record sorting by phone numbers
- • Scientific computing: Particle simulation data sorting
- • Web analytics: Sorting page views by visitor ID
💡 Historical Note
Radix sort is one of the oldest sorting algorithms, originally developed for use withpunch card machines in the early 20th century. The mechanical card sorters would literally sort cards into buckets based on the holes punched in each column, processing one column at a time - exactly like modern radix sort!