基数排序

基数排序

6.1 思路

基数排序是一种非比较型整数排序算法,其原理是将整数按位数分组,对每一位进行桶排序。

  • 基数排序从低位向高位排序,将整数分为个位、十位、百位等不同的数位。
  • 再将每一位数位上的数字分别放入桶中进行排序,最后将排好序的数字从桶中取出。

基数排序是桶排序的扩展,用于整数排序,与桶排序相比,其多了一重循环,用于不同数位的比较。

基数排序适用于整数排序,特别是位数大小不一的整数排序,比如电话号码、银行卡号等。

基数排序的优点:

  1. 稳定性:基数排序是稳定的排序算法,排序后,相同的数字的相对位置不变。
  2. 时间复杂度低:基数排序的时间复杂度为O(n * k),k为数字的位数。
  3. 适用范围广:基数排序适用于数据范围很大的场景,如数字的位数不多。

基数排序的缺点:

  1. 需要额外的存储空间:基数排序需要使用一些额外的存储空间存储桶,占用额外的空间。
  2. 数据结构不同导致不能比较:基数排序只适用于整数数字,不能对其他数据结构进行排序。

6.2 动图展示

6.3 基数排序流程

  1. 根据待排序的数的位数,确定需要进行的趟数,每一趟按照对应的位数进行排序。
  2. 创建10个桶,分别代表0~9的数字,存储对应位数上数字为该数字的数。
  3. 遍历待排序数组,将每一个数字按照其对应位数上的数字放入对应的桶中。
  4. 按照桶的顺序依次遍历每一个桶,将桶中的数字存入辅助数组中。
  5. 将辅助数组的数字复制回原数组中。
  6. 如果还有多余的趟数,则从第2步开始重复上述操作,直到所有的趟数都已经结束。
  7. 排序完成。

6.4 基数排序代码

function radixSort(arr: number[]) {
  const maxDigit = getMaxDigit(arr); // 获取最大位数

  for (let i = 0; i < maxDigit; i++) {
    let buckets: number[][] = []; // 创建桶

    for (let j = 0; j < arr.length; j++) {
      let digit = getDigit(arr[j], i); // 获取数字的第i位数字

      if (!buckets[digit]) {
        buckets[digit] = [];
      }

      buckets[digit].push(arr[j]); // 将数字放入相应的桶中
    }

    arr = [].concat(...buckets); // 将桶中的数字取出来,重新放入arr数组中
  }

  return arr;
}

// 获取最大位数
function getMaxDigit(arr: number[]) {
  let max = 0;

  for (let i = 0; i < arr.length; i++) {
    let digit = getDigitCount(arr[i]);
    max = Math.max(max, digit);
  }

  return max;
}

// 获取数字的位数
function getDigitCount(num: number) {
  if (num === 0) return 1;

  return Math.floor(Math.log10(Math.abs(num))) + 1;
}

// 获取数字的第i位数字
function getDigit(num: number, i: number) {
  return Math.floor(Math.abs(num) / Math.pow(10, i)) % 10;
}

整体流程分为两步:

  1. 从低位到高位依次排序,每一位排序时都是使用计数排序的思想。
  2. 从最低位的排序结果开始,依次累加上一位的排序结果,得到最终的排序结果。

具体实现过程中,使用了一个二维数组作为桶,桶的第一维是数字的每一位,第二维是存储这一位数字相同的数字的数组。

使用了两个循环,外层循环进行排序的次数,内层循环进行元素的遍历。

最终,排序完成后,把结果存入原数组,完成排序。

6.5 基数排序的时间复杂度

基数排序的时间复杂度分析:

  1. 对于单次排序,基数排序的时间复杂度为 O(n),因为每个数都只需要进行一次排序。
  2. 对于整个排序过程,基数排序的时间复杂度为 O(d(n + k)),其中 d 为位数,n 为数组长度,k 为桶的数量。
    • 在最坏情况下,当所有数的位数都相同时,d 与 n 的值相同,所以时间复杂度可以看做 O(n^2)。

基数排序的空间复杂度分析:

  1. 基数排序的空间复杂度为 O(n + k),其中 n 为数组长度,k 为桶的数量。
  2. 需要额外的数组存储排序的中间结果,空间复杂度为 O(n)。

6.6 基数排序小结

基数排序是一种非比较型整数排序算法,适用于大量数,很长的数列。它是桶排序的一种改进版本。它的基本思想是:将整数按位数切割成不同的数字,然后按每个位数分别比较。具体来说,就是将数列分别按个位,十位,百位... 的大小顺序排序,最后组合在一起。

优点:

  1. 时间复杂度稳定,为O(n * k),其中n为数列的长度,k为数列中数的最大位数。
  2. 空间复杂度小,只需要额外的常数空间。
  3. 是稳定的排序算法,也就是说,相同的数字排序后仍然相同。

缺点:

  1. 不适用于浮点数和负数。
  2. 对于数据范围较大的数列,k的大小也很大,因此,时间复杂度可能较高。

总体来说,基数排序是一种非常有效的整数排序算法,特别是对于大量数,很长的数列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值