一种非比较排序,他是对一些关键字进行分类收集的一种排序方法,比如我们数字可以按照个位、十位、百位….

    对于普通数字比较来说我们可以类比计数排序和桶排序
    基数排序:根据键值的每位数字来分配桶
    计数排序:每个桶只存单一键值
    桶排序:每个桶存一定范围的值

    算法思路:
    1、确定序列的关键字并对其进行分类(个位、十位,百位…)
    2、对于每一次分类的结果进行关键字排序,然后输出

    举例子:
    比如序列 [ 3, 4, 6, 2, 1, 6, 95, 2, 5, 7, 288, 45, 53, 334, 581 ]
    第一步:对个位进行计数排序得到 [ 1, 581, 2, 2, 3, 53, 4, 334, 95, 5, 45, 6, 6, 7, 288]
    第二步:对十位进行计数排序得到 [ 1, 2, 2, 3, 4, 5, 6, 6, 7, 334, 45, 53, 581, 288, 95]
    第三部:对百位进行计数排序得到 [ 1, 2, 2, 3, 4, 5, 6, 6, 7, 45, 53, 95, 288, 334, 581]
    完毕

    代码

    1. function RadixSort(nums){
    2. let digitNumber = 1 // 分类的数量
    3. for (let j = 0; j < nums.length; j++) { // 找到最大位
    4. digitNumber = Math.max(digitNumber, nums[j].toString().length) // 确定最大分类数量
    5. }
    6. let div = 1, mod = 10, count = new Array(20) // 数字每一位只有-9 - 9, 实际19个,为了方便记忆我们计为20个
    7. for (let i = 0; i < digitNumber; i++, div*=10, mod*=10) {
    8. for (let j = 0; j < nums.length; j++) {
    9. let buncket = parseInt(nums[j] % mod / div) // 对应个、百..位 位置上的桶编号
    10. buncket += 10 // 处理负数,把数字偏移右10位(实际只需要9位)
    11. count[buncket] = count[buncket] || []
    12. count[buncket].push(nums[j])
    13. }
    14. let pos = 0
    15. for (let j = 0; j < count.length; j++) {
    16. if(count[j]){
    17. while(count[j].length){ // 依次输出到原数组中
    18. nums[pos++] = count[j].shift()
    19. }
    20. }
    21. }
    22. }
    23. return nums
    24. }

    时间复杂度O(k * n) k指代分类的总数,但是通常k是一个比较小的常数
    空间复杂度(O(n + k))

    稳定性而言,每次分类排序采用的稳定的计数排序,所以是稳定的