Radix Sort
Note
This page does not cover Counting Sort.
This page briefly introduces radix sort.
Definition
Radix sort is a non-comparative sorting algorithm originally used to solve card sorting problems. Radix sort splits the elements to be sorted into \(k\) keywords and sorts each keyword sequentially to complete the sorting of all elements.
If the comparison proceeds from the 1st keyword to the \(k\)-th keyword, it is called MSD (Most Significant Digit first) radix sort;
If the comparison proceeds from the \(k\)-th keyword to the 1st keyword, it is called LSD (Least Significant Digit first) radix sort.
Comparison of Elements with k Keywords
Let \(a_i\) denote the \(i\)-th keyword of element \(a\).
If an element has \(k\) keywords, the default comparison method for two elements \(a\) and \(b\) is:
- Compare the 1st keyword \(a_1\) and \(b_1\) of the two elements. If \(a_1 < b_1\), then \(a < b\); if \(a_1 > b_1\), then \(a > b\); if \(a_1 = b_1\), proceed to the next step;
- Compare the 2nd keyword \(a_2\) and \(b_2\) of the two elements. If \(a_2 < b_2\), then \(a < b\); if \(a_2 > b_2\), then \(a > b\); if \(a_2 = b_2\), proceed to the next step;
- ……
- Compare the \(k\)-th keyword \(a_k\) and \(b_k\) of the two elements. If \(a_k < b_k\), then \(a < b\); if \(a_k > b_k\), then \(a > b\); if \(a_k = b_k\), then \(a = b\).
Examples:
- When comparing natural numbers, align them by the units digit and pad with zeros towards higher digits. Then the \(i\)-th digit from left to right can serve as the \(i\)-th keyword;
- When comparing strings based on lexicographical order, the \(i\)-th character from left to right can serve as the \(i\)-th keyword;
- The default comparison method for C++'s
std::pairandstd::tupleis the same as described above.
MSD Radix Sort
Based on the comparison method for elements with \(k\) keywords, one can think: first compare the 1st keyword of all elements to roughly determine their relative order; then for elements with the same 1st keyword, compare their 2nd keyword, and so on.
Since the comparison proceeds from the 1st keyword to the \(k\)-th keyword, the sorting algorithm derived from this idea is called MSD (Most Significant Digit first) radix sort.
Algorithm Process
Split the elements to be sorted into \(k\) keywords. First perform a stable sort on the 1st keyword, then for each group of elements with the same keyword, perform a stable sort on the 2nd keyword (recursively), and so on. Finally, for each group of elements with the same keyword, perform a stable sort on the \(k\)-th keyword.
Generally, we assume radix sort is stable, so in MSD radix sort, we only consider using a stable algorithm (usually counting sort) to sort the keywords internally.
Correctness refers to the comparison of elements with \(k\) keywords above.
Reference Code
Sorting Natural Numbers
Below is C++ reference code using iterative MSD radix sort to sort elements within the unsigned int range. The values of \(W\) and \(\log_2 W\) can be adjusted (it is recommended to set \(\log_2 W\) to \(2^k\) for bitwise optimization).
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
Sorting Strings
Below is C++ reference code using iterative MSD radix sort to sort null-terminated byte strings based on lexicographical order:
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
Since comparing two strings can easily reach \(O(n)\) linear complexity, MSD radix sort is superior to most comparison-based sorting algorithms in both time complexity and actual runtime for string sorting.
Relationship with Bucket Sort
Prerequisite: Bucket Sort
Bucket sort requires other sorting algorithms to sort the elements inside each bucket. However, it is entirely possible to perform bucket sort on each bucket recursively until the number of elements in a bucket is \(\le 1\).
Therefore, another way to understand MSD radix sort is: bucket sort implemented using bucket sort.
Consequently, an optimization method for the time constant of MSD radix sort can be proposed: if at some step the number of elements in a bucket is \(\le B\) (where \(B\) is a self-chosen constant), directly perform insertion sort and return, reducing the recursion depth.
LSD Radix Sort
MSD radix sort compares from the 1st keyword to the \(k\)-th keyword, requiring recursion or iteration, which results in a larger time constant and is somewhat inconvenient for comparing natural numbers.
Reversing the recursive operation: comparing from the \(k\)-th keyword to the 1st keyword yields LSD (Least Significant Digit first) radix sort, a sorting algorithm that can be implemented without recursion.
Algorithm Process
Split the elements to be sorted into \(k\) keywords. First perform a stable sort on the \(k\)-th keyword for all elements, then perform a stable sort on the \((k-1)\)-th keyword for all elements, then perform a stable sort on the \((k-2)\)-th keyword for all elements, and so on. Finally, perform a stable sort on the 1st keyword for all elements, thus completing a stable sort of the entire sequence.

LSD radix sort also requires a stable algorithm to sort the keywords internally. Similarly, counting sort is typically used.
The correctness of LSD radix sort can be referred to in Introduction to Algorithms (Third Edition), Exercise 8.3-3 Solution or explained as follows:
Correctness
Recall the comparison method for elements with \(k\) keywords:
- To determine the order of two elements \(a\) and \(b\) via \(a_1\) and \(b_1\), we need to know the conclusion from comparing \(a_2\) and \(b_2\) in advance to handle the case \(a_1 = b_1\);
- To determine the order via \(a_2\) and \(b_2\), we need to know the conclusion from comparing \(a_3\) and \(b_3\) in advance to handle the case \(a_2 = b_2\);
- ……
- To determine the order via \(a_{k-1}\) and \(b_{k-1}\), we need to know the conclusion from comparing \(a_k\) and \(b_k\) in advance to handle the case \(a_{k-1} = b_{k-1}\);
- \(a_k\) and \(b_k\) can be compared directly.
Now, reverse the order:
- \(a_k\) and \(b_k\) can be compared directly;
- After knowing the conclusion from comparing \(a_k\) and \(b_k\), we can derive the conclusion for comparing \(a_{k-1}\) and \(b_{k-1}\);
- ……
- After knowing the conclusion from comparing \(a_2\) and \(b_2\), we can derive the conclusion for comparing \(a_1\) and \(b_1\);
- After knowing the conclusion from comparing \(a_1\) and \(b_1\), we finally derive the conclusion for comparing \(a\) and \(b\).
During this process, by comparing and rearranging the elements for each keyword, we obtain LSD radix sort.
Pseudocode
Reference Code
Below is an implementation of LSD radix sort for sorting elements with \(k\) keywords.
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Actually, it is not necessary to enumerate from back to front for a stable sort; performing an operation equivalent to std::exclusive_scan on the cnt array suffices.
Example Problem Luogu P1177【Template】Quick Sort
Given \(n\) positive integers, output them in ascending order.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
Properties
Stability
If the internal sorting of keywords is stable, both MSD radix sort and LSD radix sort are stable sorting algorithms.
Time Complexity
Generally, radix sort is faster than comparison-based sorting algorithms (like quicksort). However, due to the need for additional memory space, when memory is scarce, in-place algorithms (like quicksort) might be a better choice.1
Typically, if the value range of each keyword is not large, counting sort can be used as the internal sorting, resulting in a complexity of \(O(kn+\sum\limits_{i=1}^k w_i)\), where \(w_i\) is the size of the value range of the \(i\)-th keyword. If the keyword value range is large, one can directly use a comparison-based \(O(nk\log n)\) sort without resorting to radix sort.
Space Complexity
The space complexity of both MSD radix sort and LSD radix sort is \(O(k+n)\).
References and Notes
-
Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms (3rd ed.). MIT Press and McGraw-Hill, 2009. ISBN 978-0-262-03384-8. "8.3 Radix sort", pp. 199. ↩
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用