计数排序是什么
计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,快于任何比较排序算法
计数排序实现图
目录
- 第一版
- 思路
- 代码实现
- 第二版
- 思路
- 代码实现
第一版
思路
例如我现在有 一组 5 个数的数组需要进行排序
let arr = [2,6,3,8,1];
那我们想到得到的结果肯定是
let arr = [1,2,3,6,8];
所以需要进行排序
那我先定义一个需要排序的数组
let arr = [2,6,3,8,1];
这时候我会想,如果我把这些数据都存放到一个空的数组中的索引去,然后依次输出索引不就是排序完成了吗? 一不做二不休,试试呗,试试又不会怀孕.
let arr = [2,6,3,8,1];
let arr1 = new Array(10);
我定义一个长度为 10的数组,而这样子定义数组,数组中的值就默认会是undefined;就会出现以下的情况
//let arr = [2,6,3,8,1];
//let arr1 = [undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined];
我现在数组中是 2,6,3,8,1,那么我则在 arr1中的对应索引中,随便输入一个值代替即可,也就是演变成以下的样子
//let arr = [2,6,3,8,1];
//let arr1 = [6,6,6,undefined,undefined,6,undefined,6,undefined,undefined];
最后我再次循环 arr1中的数组, 如果arr1中的数组的数据是 =6,那么则输出对应索引
思路完毕,代码实现
//1. 定义需要排序的数组
let arr = [2, 6, 3, 8, 1];
//2. 定义数组接受需要排序的数组
let arr1 = new Array(10);
//3. 循环遍历需要排序的数组
for (let i = 0; i < arr.length; i++) {
//4. 循环并且插入到新数组中去
arr1[arr[i]] = 6;
}
// console.log(arr1);
//5.遍历接受排序的数组
for (let i = 0; i < arr1.length; i++) {
//6. 判断arr1里面对应的值是否等于6 , 等于6就输出
if(arr1[i] === 6){
console.log(i); //1,2,3,6,8
}
}
ok , 功能是实现了 , 排序也实现了 ,但是其实这样子做的话, 还有几个地方是不好的
- 限制只能排序
10个数,超过十个数就要更改代码了 - 只能排序单数据,不能存在重复数据(因为索引只有一个)
第二版
在第二版中,我们要改进的就是上面的三个缺陷
思路
- 限制只能排序
10个数,超过十个数就要更改代码了 - 只能排序单数据,不能存在重复数据(因为索引只有一个)
//原本的
let arr1 = new Array(10);
让 arr1 的数组长度等于需要排序的数组的长度 + 10 作为基数
//改进后
let arr1 = new Array(arr.length + 10);
- 只能排序单数据,不能存在重复数据(因为索引只有一个)
因为我们的
arr1采用的是直接使用6来填充数据,所以,你索引填写一次之后,第二次再填写,不也还是6嘛,所以需要更改他的填写方式
//原本的
for (let i = 0; i < arr.length; i++) {
arr1[arr[i]] = 6;
}
//改进后
arr1.fill(0); //设置数组中所有的元素值为0
for (let i = 0; i < arr.length; i++) {
arr1[arr[i]] = arr1[arr[i]] + 1;
}
表现样子 1
let arr = [2,6,3,8,3];
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 索引号
let arr1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
当循环过后
let arr = [2,6,3,8,3];
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 索引号
let arr1 = [0, 0, 1, 2, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
而重复了的就是会变成
2, 所以我们就可以根据数量进行输出
思路完毕,代码实现
//1. 定义需要排序的数组
let arr = [2, 6, 3, 8, 3];
//let arr = [9,5,8,7,2,3,5,1,7,2,3,5,7,6,8,9,2,1,3,5];
//2. 定义需要接受排序的数组
let arr1 = new Array(arr.length + 10);
//3. 把arr1的值全部置零
arr1.fill(0);
//4. 循环遍历arr
for (let i = 0; i < arr.length; i++) {
//5. 循环一次如果有值就+ 1,遇到重复的就再次 + 1
arr1[arr[i]] = arr1[arr[i]] + 1;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 索引号
//[0, 0, 1, 2, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
}
//6.遍历接受排序的数组
//7.定义一个接受返回值的数组
let arr3 = [];
for (let i = 0; i < arr1.length; i++) {
//7.遍历接受排序的数组里面的元素
for (let j = 0; j < arr1[i]; j++) {
arr3.push(i);
}
}
console.log(arr3); //[2, 3, 3, 6, 8]
封装方法实现:
/**
* @param arr 接受需要排序的数组
* @param maxNum 接受数组中的最大值
*/
function countSort(arr, maxNum) {
let arr1 = arr;
let arr2 = new Array(maxNum);
arr2.fill(0);
for (let i = 0; i < arr1.length; i++) {
arr2[arr1[i]]++;
}
let arr3 = [];
for (let i = 0; i < arr2.length; i++) {
for (let j = 0; j < arr2[i]; j++) {
arr3.push(i);
}
}
return arr3;
}
let arr = [1,5,7,2,2,5,4,9];
let result = countSort(arr,9);
console.log(result); //[1, 2, 2, 4, 5, 5, 7]