• 计数排序+桶排序 详讲(思路+图解+代码详解)



    计数排序和桶排序


    一、计数排序

    在这里插入图片描述

    • 时间复杂度:
    • 空间复杂度:
    • 稳定性:稳定
    概念:
    • 非基于比较的排序

    • 计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用

      1.统计相同元素出现的个数

      2.根据统计的结果将序列回收到原来的序列中

    • 计数排序使用的场景:给出指定范围内的数据进行排序

    • 使用场景:一组集中在某个范围内的数据

    写法一:
    • 通过遍历计数数组,循环输出计数数组存的次数

    在这里插入图片描述

    • 1.遍历数组找到最小值最大值
    • 2.根据最大最小值,申请一个计数数组
    • 3.遍历待排数组进行计数
    • 4.遍历计数数组进行输出
     /**
         * 计数排序
         *无法保证稳定
         * @param array
         */
        public static void countSort2(int[] array) {
            //1.遍历数组找到最大值和最小值
            int MAX = array[0];
            int MIN = array[0];
            for (int i = 1; i < array.length; i++) {
                if (array[i] > MAX) {
                    MAX = array[i];
                }
                if (array[i] < MIN) {
                    MIN = array[i];
                }
            }
            //2.根据最大最小值,申请一个计数数组
            int len = MAX - MIN + 1;//长度
            int[] count = new int[len];
    
            //3. 遍历待排数组进行计数
            for (int i = 0; i < array.length; i++) {
                count[array[i] - MIN]++;
            }
    
            //4.遍历计数数组进行输出
            int index = 0;//array数组新的下标
            for (int i = 0; i < count.length; i++) {
                while (count[i] > 0) {
                    array[index] = i + MIN;//+最小值,求出真正的数
                    count[i]--;
                    index++;
                }
            }
        }
    
    • 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
    写法二:
    • 写定数组的大小,用临时数组存储结构
    • 计算每个元素在排序后的数组中的最终位置
    • 根据计数数组将元素放到临时数组b中,实现排序
    • 从后往前,根据原来数组的内容,在计数数组中找到要填写在b数组中的位置,
    • 计数数组记录的不再是数字出现是次数,而是应该在数组中存放的位置下标

    在这里插入图片描述

     /**
         * 计数排序
         *稳定
         * @param array
         */
        public static void countSort(int[] array) {
            int len = array.length;
            final int MAX = 256;//常量确定数组大小
            int[] c = new int[MAX];//计数数组
            int[] b = new int[MAX];//临时数组,存放结果
    
            //统计每个元素的出现次,进行计数
            for (int i = 0; i < len; i++) {
                c[array[i]]++;// 将a[i]作为索引,对应计数数组c中的位置加1
            }
    
            // 计算每个元素在排序后的数组中的最终位置
            for (int i = 1; i < MAX; i++) {
                c[i] += c[i - 1];// 计数数组中每个元素的值等于它前面所有元素的值之和
            }
    
            // 根据计数数组将元素放到临时数组b中,实现排序
            for (int i = len - 1; i >= 0; i--) {
                b[c[array[i]] - 1] = array[i];// 将a[i]放入临时数组b中的正确位置
                c[array[i]]--;// 对应计数数组c中的位置减1,确保相同元素能够放在正确的位置
            }
            // 将临时数组b中的元素复制回原数组a,完成排序
            for (int i = 0; i < len; i++) {
                array[i] = b[i];
            }
        }
    
    
    • 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

    二、桶排序

    概念

    划分多个范围相同的区间,每个子区间自排序,最后合并

    • 桶排序是计数排序的扩展版本,计数排序:每个桶只存储单一键值

    • 桶排序: 每个桶存储一定范围的数值,确定桶的个数和范围

    • 将待排序数组中的元素映射到各个对应的桶中,对每个桶进行排序

    • 最后将非空桶中的元素逐个放入原序列中

    在这里插入图片描述

    代码
        public static void bucketSort(int[] array){
    
            // 计算最大值与最小值
            int max = Integer.MIN_VALUE;
            int min = Integer.MAX_VALUE;
            for(int i = 0; i < array.length; i++){
                max = Math.max(max, array[i]);
                min = Math.min(min, array[i]);
            }
    
            // 计算桶的数量
            int bucketNum = (max - min) / array.length + 1;
            ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
            for(int i = 0; i < bucketNum; i++){
                bucketArr.add(new ArrayList<Integer>());
            }
    
            // 将每个元素放入桶
            for(int i = 0; i < array.length; i++){
                int num = (array[i] - min) / (array.length);
                bucketArr.get(num).add(array[i]);
            }
    
            // 对每个桶进行排序
            for(int i = 0; i < bucketArr.size(); i++){
                Collections.sort(bucketArr.get(i));
            }
    
            // 将桶中的元素赋值到原序列
            int index = 0;
            for(int i = 0; i < bucketArr.size(); i++){
                for(int j = 0; j < bucketArr.get(i).size(); j++){
                    array[index++] = bucketArr.get(i).get(j);
                }
            }
        }
    
    
    • 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

    点击移步博客主页,欢迎光临~

    偷cyk的图

  • 相关阅读:
    基于MetaTown构建数字资产平台
    一文了解Linux上TCP的几个内核参数调优
    C语言学生成绩管理系统(二叉排序树)
    Qt开发经验小技巧246-250
    动态内存管理(2)
    OpenHarmony AI 业务子系统
    【办公软件】案例:电路中计算出的电阻值为5欧,怎么通过Excel匹配到仓库里最接近的电阻值?
    从零开始的c语言日记day35——数据在内存中的储存
    go语言 反向代理
    不是冤家不碰头:贝索斯和马斯克入选福布斯“全球最抠门亿万富豪”榜单
  • 原文地址:https://blog.csdn.net/m0_64003319/article/details/134540450