js实现计数排序的一种方法

397 阅读1分钟

时间复杂度:O(n)

空间复杂度:O(n)

属于稳定排序,需要新增临时存储空间,不属于原地排序

局限性:

1.当数列最大值和最小值差距过大 不适合。 2.数列元素不是整数 不适合

第一步:找出数组中最大值和最小值,然后计算出差值d。

第二步:新建一个长度为d的统计数组(这个数组就相当于桶排序中的“桶”),存储待排序数组中每个值出现的次数(比如:统计数组的长度直接取0-arr[max],那每个位置的值就代表arr[i]出现了几次)。

第三步:遍历待排序数组,填充统计数组。

🌟第四步:对统计数组做变形,后面的元素等于前面的元素个数之和(变形后的数组,每个位置的值,代表小于等于原数据的值有多少个)(这一步操作的目的就是为了让统计数组存储的值,等于相应待排序数组值的最终排序位置的序号。有点难理解,因为这儿就是计数排序的精髓。。。)。

第五步:倒叙遍历原始数组,然后从统计数组找到正确位置,统计数组的当前位置值-1。

第六步:输出结果数组。

/**
 *
 * @param {待排序数组} arr
 * @returns 排序完成的数组
 * 
 */
function countSort(arr) {
  // 1.找出数组中最大值和最小值,然后计算出差值
  let max = arr[0];
  let min = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
    if (arr[i] < min) {
      min = arr[i];
    }
  }
  let d = max - min;

  // 2.新建一个长度为d的统计数组
  let countArr = new Array(d + 1).fill(0);
  // 3.遍历数组,填充统计数组(此时数组里每个位置的值,代表多少个)
  for (let i = 0; i < arr.length; i++) {
    // 这样能保证所有数据都能统计进这个数组
    countArr[arr[i] - min]++;
  }

  // 4.统计数组做变形,后面的元素等于前面的元素之和
  for (let i = 1; i < countArr.length; i++) {
    countArr[i] += countArr[i - 1];
  }

  // 5.倒叙遍历原始数组,从统计数组找到正确位置,输出到结果数组中
  let sortedArr = new Array(arr.length);
  for (let i = arr.length - 1; i >= 0; i--) {
    sortedArr[countArr[arr[i] - min] - 1] = arr[i];
    countArr[arr[i] - min]--;
  }
  return sortedArr;
}