基数排序是一种排序算法,它通过首先对相同位值的各个数字进行分组来对元素进行排序。然后,根据元素的递增/递减顺序对元素进行排序。
假设我们有一个包含 8 个元素的数组。首先,我们将根据单位位置的值对元素进行排序。然后,我们将根据第十位的值对元素进行排序。这个过程一直持续到最后一个重要的地方。
设初始数组为[121, 432, 564, 23, 1, 45, 788]。如下图所示按照基数排序。
![]() |
|---|
| 基数排序的工作 |
请在阅读本文之前先了解计数排序,因为计数排序是基数排序中的一种中间排序。
算法的图解
- 找到数组中最大的元素,即 最大值. 让X成为 中的位数max。X计算是因为我们必须遍历所有元素的所有重要位置。
在这个数组中[121, 432, 564, 23, 1, 45, 788],我们有最大的数字 788。它有 3 位数字。因此,循环应该达到数百个位置(3 次)。
- 现在,一个一个地浏览每一个重要的地方。
使用任何稳定的排序技术对每个重要位置的数字进行排序。我们为此使用了计数排序。
根据单位位数字 ( X=0)对元素进行排序。
![]() |
|---|
| 使用计数排序根据单位位置对元素进行排序 |
- 现在,根据十位数字对元素进行排序。
|
|
| —- |
| 根据十位对元素进行排序 |
- 最后,根据百位的数字对元素进行排序。
|
|
| —- |
| 根据数百个位置对元素进行排序 |
算法的伪码
radixSort(array)d <- maximum number of digits in the largest elementcreate d buckets of size 0-9for i <- 0 to dsort the elements according to ith place digits using countingSortcountingSort(array, d)max <- find largest element among dth place elementsinitialize count array with all zerosfor j <- 0 to sizefind the total count of each unique digit in dth place of elements andstore the count at jth index in count arrayfor i <- 1 to maxfind the cumulative sum and store it in count array itselffor j <- size down to 1restore the elements to arraydecrease count of each element restored by 1
算法的实现
// Radix Sort in Java Programmingimport java.util.Arrays;class RadixSort {// Using counting sort to sort the elements in the basis of significant placesvoid countingSort(int array[], int size, int place) {int[] output = new int[size + 1];int max = array[0];for (int i = 1; i < size; i++) {if (array[i] > max)max = array[i];}int[] count = new int[max + 1];for (int i = 0; i < max; ++i)count[i] = 0;// Calculate count of elementsfor (int i = 0; i < size; i++)count[(array[i] / place) % 10]++;// Calculate cumulative countfor (int i = 1; i < 10; i++)count[i] += count[i - 1];// Place the elements in sorted orderfor (int i = size - 1; i >= 0; i--) {output[count[(array[i] / place) % 10] - 1] = array[i];count[(array[i] / place) % 10]--;}for (int i = 0; i < size; i++)array[i] = output[i];}// Function to get the largest element from an arrayint getMax(int array[], int n) {int max = array[0];for (int i = 1; i < n; i++)if (array[i] > max)max = array[i];return max;}// Main function to implement radix sortvoid radixSort(int array[], int size) {// Get maximum elementint max = getMax(array, size);// Apply counting sort to sort elements based on place value.for (int place = 1; max / place > 0; place *= 10)countingSort(array, size, place);}// Driver codepublic static void main(String args[]) {int[] data = { 121, 432, 564, 23, 1, 45, 788 };int size = data.length;RadixSort rs = new RadixSort();rs.radixSort(data, size);System.out.println("Sorted Array in Ascending Order: ");System.out.println(Arrays.toString(data));}}
算法复杂度
| 时间复杂度 | |
|---|---|
| 最好的 | O(n+k) |
| 最差 | O(n+k) |
| 平均 | O(n+k) |
| 空间复杂度 | O(max) |
| 稳定 | 是的 |
由于基数排序是一种非比较算法,因此它相比比较排序算法具有优势。对于使用计数排序作为中间稳定排序的基数排序,时间复杂度为O(d(n+k))。
这里,d是循环数,O(n+k)是计数排序的时间复杂度。因此,基数排序具有比O(nlog n)比较排序算法更好的线性时间复杂度。如果我们采用非常大的数字或其他基数,如 32 位和 64 位数字,那么它可以在线性时间内执行,但是中间排序需要很大的空间。这使得基数排序空间效率低下。这就是为什么在软件库中不使用这种排序的原因。
算法的应用
- DC3 算法 (Kärkkäinen-Sanders-Burkhardt) 同时制作后缀数组。
- 有大范围数字的地方。
相似的算法
- 快速排序
- 归并排序
- 桶排序
- 计数排序


