概念
计数排序是一个排序时不比较元素大小的排序算法。
算法原理
- 比如我们有如下原始数组:
[88,82,82,86,82,88,88,85,85,84]
- 紧接着,分别求出原始数组的最小值和最大值:
82
、88
,求出计数数组长度7
// 1. 先求出最大值和最小值
let min = arr[0]
let max = arr[1]
for(let i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i]
}
if (arr[i] > max) {
max = arr[i]
}
}
const length = max - min + 1
- 初始化一个长度为7的计数数组,值均初始化为0
- 遍历原始数组,计数数组下标对应的值得个数,比如
0
对应82
共有3个,那么temp[0]=3
// 填充计数数组
const temp = Array(length).fill(0)
for (let i = 0; i < arr.length; i++) {
temp[arr[i] - min]++
}
- 将数组变形,使计数数组的元素等于加上前面元素的值之和
// 计数数组形变,后面的元素等于前面的元素之和
let sum = 0
for (let i = 0; i < length; i++) {
sum += temp[i]
temp[i] = sum
}
此时计数数组结果为:
- 倒序遍历原始数组 先声明一个输出数组,然后倒序遍历原始数组:
-
- 取出最后一个数
84
,此数下标为9
,获取其对应的计数数组的的下标[arr[i] - min]
:84-82
:2
;
- 取出最后一个数
-
- 计数数组的前一个的下标对应的值是
temp[[arr[i] - min]]
:4
,即84
对应的排序是4-1
;
- 计数数组的前一个的下标对应的值是
-
- 每取出一个,当前数对应的计数数组下标
[arr[i] - min]
要-1,即此时temp[2]--
,变为3
- 每取出一个,当前数对应的计数数组下标
let result = []
for (let i = 0; i < arr.length; i++) {
result[temp[arr[i] - min] - 1] = arr[i]
temp[arr[i] - min]--
}
算法代码
function countSort(arr) {
// 1. 先求出最大值和最小值
let min = arr[0]
let max = arr[1]
for(let i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i]
}
if (arr[i] > max) {
max = arr[i]
}
}
const length = max - min + 1
// 填充计数数组
const temp = Array(length).fill(0)
for (let i = 0; i < arr.length; i++) {
temp[arr[i] - min]++
}
// 计数数组形变,后面的元素等于前面的元素之和
let sum = 0
for (let i = 0; i < length; i++) {
sum += temp[i]
temp[i] = sum
}
let result = Array(arr.length)
for (let i = arr.length - 1; i >=0; i--) {
result[temp[arr[i] - min] - 1] = arr[i]
temp[arr[i] - min]--
}
return result
}