排序算法(五):基数排序

概念

基数排序是非比较排序算法,算法的时间复杂度是O(n). 相比于快速排序的O(nlgn),从表面上看具有不小的优势.但事实上可能有些出入,因为基数排序的n可能具有比较大的系数K.因此在具体的应用中,应首先对这个排序函数的效率进行评估. 基数排序的主要思路是,将所有待比较数值(注意,必须是正整数)统一为同样的数位长度,数位较短的数前面补零. 然后, 从最低位开始, 依次进行一次稳定排序(我们常用上一篇blog介绍的计数排序算法, 因为每个位可能的取值范围是固定的从0到9).这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列.

时间复杂度
最好:O(n * k),k表示最大值的位数。

最坏:O(n * k)

平均:O(n * k)
演示
[399 ,298,98,1] 的排序过程

1.先把数据变成相同位数的值

399
298
098
001

2. 从个位数开始遍历
    
001
298
098
399

3 十位数遍历

001
298
098
399

4. 百位数遍历

001
098
298
399

可想而知,如果是数据量特别大的数,这种处理会非常费劲

代码
  function radix_sort(nums) {
      // 计算位数
      function getDigits(n) {
        let sum = 0;
        while (n) {
          sum++;
          n = parseInt(n / 10);
        }
        return sum;
      }
      // 第一维表示位数即0-9,第二维表示里面存放的值
      let arr = Array.from(Array(10)).map(() => Array());
      let max = Math.max(...nums);
      //算出来最大的是 几位数
      let maxDigits = getDigits(max);

      for (let i = 0, len = nums.length; i < len; i++) {
        // 用0把每一个数都填充成相同的位数
        nums[i] = (nums[i] + '').padStart(maxDigits, 0);
        // 先根据个位数把每一个数放到相应的桶里
        let temp = nums[i][nums[i].length - 1];
        arr[temp].push(nums[i]);
      }
      // 循环判断每个位数
      for (let i = maxDigits - 2; i >= 0; i--) {
        // 循环每一个桶
        for (let j = 0; j <= 9; j++) {
          let temp = arr[j]
          let len = temp.length;
          // 根据当前的位数i把桶里的数放到相应的桶里
          while (len--) {
            let str = temp[0];
            temp.shift();
            arr[str[i]].push(str);
          }
        }
      }
      // 修改回原数组
      let res = [].concat.apply([], arr);
      nums.forEach((val, index) => {
        nums[index] = +res[index];
      })
    }

    var sortArr = [9, 6, 3, 5, 2, 1, 7, 343, 6, 643, 243, 544, 5, 63, 234, 0, 56, 123]
    radix_sort(sortArr)
    console.log(sortArr)
    // [0, 1, 2, 3, 5, 5, 6, 6, 7, 9, 56, 63, 123, 234, 243, 343, 544, 643]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值