时间复杂度: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;
}