基数排序(桶排序)

先决条件

  • 将[0,1,5,2,4,3,3,2]排序
  • 将元素按照大小存入数组索引中,然后根据索引内容输出
  • a[0]=1,a[2]=2,a[3]=2,a[4]=1,a[5]=1;遍历数组输出值不为0的n个元素即可,0 1 2 2 3 3 4 5;时间复杂度为O(N)

基数排序

  • [17,13,25,100,72]

  • 数组中元素位数最多的是100,长度为3,将数组中所有长度小于3的元素左边补0至3

  • [017,013,025,100,072]

  • 从个位开始,将元素按照大小存入桶中
    基数排序(桶排序)_第1张图片
    基数排序(桶排序)_第2张图片

  • 100 ,072, 013, 025, 017

  • 从十位开始,将元素按照大小存入桶中
    基数排序(桶排序)_第3张图片

  • 100,013,017,025,072

  • 从百位开始,将元素按照大小存入桶中

  • 013,017,025,072,100

  • 相同位基数越大优先级越大,然后高位越高优先级越大,最终能够实现有序

  • 比起直接按照元素大小排序,基数排序最多只用申请十个桶

优化版本,将桶位置映射成元素位置

  • 将原本存入基数出现的次数的数组,每项进行依次累加,并且数组长度为元素个数,如[013,021,011,052,062],原本数组为[0,2,2,1,0],现在为[0,2,4,5,5]
  • 现在每一位表示小于等于该索引的数有多少个,比如索引为2,表示小于等于2的有4个
  • 然后从元素数组从右往左遍历,062,2对应的值为4,说明有4个数小于等于2,则062的位置为4-1=3,a[3]=062,然后记录累加的数组对应位置-1,即[0,2,3,5,5]
  • 052,此时2对应的为3,固应该放的位置为3-1=2,a[2]=052,然后记录累加的数组对应位置-1,即[0,2,2,5,5]
  • 后面依次类推,从右往左的意义是保持原数组中元素的相对位置不变,比如052依旧在062前面
  • 通过这种方式不用通过a[1]=[011,021]这种方式去存对应的基数元素
let arr = [17, 13, 25, 100, 72];

function radixSort(arr, left, right, maxLen) {
  let i = 0,
    j = 0;
  //计数器
  let count = Array(10).fill(0);
  //桶
  let bucket = [];
  //根据数组中元素,最长的位数开始从个位遍历
  for (let d = 0; d < maxLen; d++) {
    //根据每位的大小为索引计算个数
    for (i = left; i <= right; i++) {
      j = getDigit(arr[i], d);
      count[j]++;
    }

    //累加数组,计算每一个小于等于索引的元素个数
    for (i = 1; i <= 9; i++) {
      count[i] = count[i] + count[i - 1];
    }

    //从右开始往左遍历,计算元素的真正位置
    for (i = right; i >= left; i--) {
      j = getDigit(arr[i], d);
      let index = count[j] - 1;
      bucket[index] = arr[i];
      //计算后索引值-1
      count[j]--;
    }
    //将bucket中排序后的内容,拷贝到原数组中
    for (i = left, j = 0; i <= right; i++, j++) {
      arr[i] = bucket[j];
    }
    //每轮比较后还原
    count.fill(0);
    bucket = [];
  }
  return arr;
}

//计算数组中元素最长的位数
function getMaxLen(arr) {
  let max = 0,
    res = 0;
  for (let i = 0; i < arr.length; i++) {
    max = Math.max(arr[i], max);
  }
  while (max != 0) {
    res++;
    max = Math.floor(max / 10);
  }

  return res;
}

//获取各个位上的数字,若位数高于元素则取0
function getDigit(num, d) {
  return parseInt(num / Math.pow(10, d)) % 10;
}

console.log(radixSort(arr, 0, arr.length - 1, getMaxLen(arr)));

你可能感兴趣的:(前端算法,算法,数据结构)