1. 简介

基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn), 为数组长度,k为数组中的数的最大的位数;

  1. 基数排序是按照低位先排序,然后收集;
  2. 再按照高位排序,然后再收集;
  3. 依次类推,直到最高位。

有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。

最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。

基数排序基于分别排序,分别收集,所以是稳定的。

2. 算法描述

  1. 取得数组中的最大数,并取得位数;
  2. arr为原始数组,从最低位开始取每个位组成radix数组;
  3. 对radix进行计数排序(利用计数排序适用于小范围数的特点);

基数排序动图.gif

3. 代码示例

  1. public static int[] RadixSort(int[] array) {
  2. if (array == null || array.length < 2)
  3. return array;
  4. // 1.先算出最大数的位数;
  5. int max = array[0];
  6. for (int i = 1; i < array.length; i++) {
  7. max = Math.max(max, array[i]);
  8. }
  9. int maxDigit = 0;
  10. while (max != 0) {
  11. max /= 10;
  12. maxDigit++;
  13. }
  14. int mod = 10, div = 1;
  15. ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
  16. for (int i = 0; i < 10; i++)
  17. bucketList.add(new ArrayList<Integer>());
  18. for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
  19. for (int j = 0; j < array.length; j++) {
  20. int num = (array[j] % mod) / div;
  21. bucketList.get(num).add(array[j]);
  22. }
  23. int index = 0;
  24. for (int j = 0; j < bucketList.size(); j++) {
  25. for (int k = 0; k < bucketList.get(j).size(); k++)
  26. array[index++] = bucketList.get(j).get(k);
  27. bucketList.get(j).clear();
  28. }
  29. }
  30. return array;
  31. }

4. 基数排序有两种方法

  1. MSD 从高位开始进行排序
  2. LSD 从低位开始进行排序

5. 性能分析

  1. 最佳情况:T(n) = O(n * k)
  2. 最差情况:T(n) = O(n * k)
  3. 平均情况:T(n) = O(n * k)

6. 基数排序 vs 计数排序 vs 桶排序

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

  • 基数排序
  • 根据键值的每位数字来分配桶
  • 计数排序
  • 每个桶只存储单一键值
  • 桶排序
  • 每个桶存储一定范围的数值