什么是计数排序
“计数排序”,名副其实,就是根据”计数”的方式来进行排序,所谓”计数”,就是统计每个元素重复出现的次数。
正如上述原始数列有5个数值,数值范围从1-5。
1 2
| let arr = [5,4,3,2,3,1]
|
那么,这些整数的值肯定是在1,2,3,4,5这5个数里面。
所以可以根据这个整数的取值范围,建立一个长度为6的数组(包括0,所以长度为6),数组下标从0到5,元素初始值全部为0。
1 2
| let countingArr = [0,0,0,0,0,0]
|
接着根据原始数列中元素出现的次数和顺序,加入到计数数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let countingArr = [0,0,0,0,0,0]
countingArr[5] += 1
countingArr[4] += 1
countingArr[3] += 1
countingArr[2] += 1
countingArr[3] += 1
countingArr[1] += 1
console.log(countingArr)
|
我们得到计数数组这个”统计结果”,排序就简单了。
后续的操作便是遍历数组,输出数组元素的下标值,元素的值是几,就输出几次。
1 2
| let result = [1,2,3,3,4,5]
|
总结
计数排序是使用空间换时间的排序算法,虽然使用它排序的速度很快,但是当数列的最大值最小值之间的插值鸿沟过大时,不适合计数排序(假设20个随机数,数值范围从0到10亿,就需要开辟10亿个数组空间,不仅浪费空间,而且时间复杂度也高);其次,计数排序只适合用于整数的数列元素场景,因为计数排序本身无法统计小数。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
export function findMaxValue(array, compareFn = defaultCompare) { if (array && array.length > 0) { let max = array[0]; for (let i = 1; i < array.length; i++) { if (compareFn(max, array[i]) === Compare.LESS_THAN) { max = array[i]; } } return max; } return undefined; }
export function countingSort(array) { if (array.length < 2) { return array; } const maxValue = findMaxValue(array); let sortedIndex = 0; const counts = new Array(maxValue + 1); array.forEach(element => { if (!counts[element]) { counts[element] = 0; } counts[element]++; }); counts.forEach((element, i) => { while (element > 0) { array[sortedIndex++] = i; element--; } }); return array; }
|