JavaScript 数组计数排序👊

2,601 阅读4分钟

计数排序是什么

计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,快于任何比较排序算法

计数排序实现图

目录

  • 第一版
  1. 思路
  2. 代码实现
  • 第二版
  1. 思路
  2. 代码实现

第一版

思路

例如我现在有 一组 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 , 功能是实现了 , 排序也实现了 ,但是其实这样子做的话, 还有几个地方是不好的

  1. 限制只能排序10个数,超过十个数就要更改代码了
  2. 只能排序单数据,不能存在重复数据(因为索引只有一个)

第二版

在第二版中,我们要改进的就是上面的三个缺陷

思路

  1. 限制只能排序10个数,超过十个数就要更改代码了
  2. 只能排序单数据,不能存在重复数据(因为索引只有一个)
    //原本的
     let arr1 = new Array(10);

arr1 的数组长度等于需要排序的数组的长度 + 10 作为基数

//改进后
 let arr1 = new Array(arr.length + 10);
  1. 只能排序单数据,不能存在重复数据(因为索引只有一个) 因为我们的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]

去我个人网站逛逛?