基数排序
基数排序是桶排序的扩展,因此又称“桶子法”,它是通过键值的部分信息,将要排序的元素分配至某些“桶”中,以达到排序的作用。
1. 算法思想
将各元素按位数切割成不同的数字,然后分别根据每个位数的比较结果进行排序。
2. 算法步骤
- 确定待排序序列的最大位数。
- 将所有待排序元素统一为最大数位长度(左补0)。
- 从最低位到最高位分别进行排序。
- 当最高位排序完成后,原数组变成有序序列。
3.算法分析
基数排序的执行效率非常高。我们要做的仅仅是把原始数据项从数组复制到链表中,然后再复制回去。如果待排序序列有10个数据项和 5个数位,则只需要10×2×5=100次复制:如果待排序序列有 100个数据和5个数位,则需要100×2×5=1000次复制⋯⋯复制次数和数据项的个数成正比,即O(n)。这简直就是最高效率的排序算法。
但是,当数据项增加 10倍时,一切就不一样了。关键字必须增加一位,多了一轮排序。复制的次数和数据项的个数与关键字长度成正比,可以认为关键字的长度是n的对数,因此在大多数情况下,基数排序的执行效率倒退为 O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n),和快速排序差不多。
快速排序参考这篇文章
空间复杂度很好算,它是在分配元素时使用的桶空间,即10n,达此全间复杂度为O(n)。
4.算法代码
算法代码如下:
Python
# -*- coding: utf-8 -*-# 基数排序
def radix_sort(arr) :maximum = max (arr) # 确定待排序数组中的最大位数d = 0 #d 为最大位数,初始为0while maximum != 0: # != ——不等于maximum = maximum // 10d += 1for i in range(d): # d轮排序s = [[] for k in range(10)] # 因为每一位数字都是0~9,所以建10个桶for j in arr:s[int(j /(10 ** i))%10].append(j) # 从个位数开始逐一进行分桶排序arr = [a for b in s for a in b] # 用10个桶回填原数组return arr# 调用 radix-sort函数
print(radix_sort([34, 21, 13, 2, 5, 1,55,3, 1, 8]))
Java
public static List<Integer> radixSort(List<Integer> arr) {int maximum = findMax(arr); // 确定待排序数组中的最大值int d = 0; // d 为最大位数,初始为0while (maximum != 0) {maximum /= 10;d++;}for (int i = 0; i < d; i++) { // d轮排序List<List<Integer>> buckets = new ArrayList<>();for (int k = 0; k < 10; k++) {buckets.add(new ArrayList<>());}for (int j : arr) {int digit = getDigit(j, i);buckets.get(digit).add(j);}arr = new ArrayList<>(); // 使用新的 ArrayList 替换旧的,以避免 UnsupportedOperationExceptionfor (List<Integer> bucket : buckets) {arr.addAll(bucket);}}return arr;}private static int findMax(List<Integer> arr) {int max = Integer.MIN_VALUE;for (int num : arr) {max = Math.max(max, num);}return max;}private static int getDigit(int number, int index) {int digit = number / (int) Math.pow(10, index);digit %= 10;return digit;}@Testvoid contextLoads () {List<Integer> arr = List.of(34, 21, 13, 2, 5, 1, 55, 3, 1, 8);arr = radixSort(arr);System.out.println(arr);}
5.输出结果
代码输出结果如下: