算法学习笔记(十)

本文详细介绍了计数排序的基本原理和实现过程,通过实例展示了如何对整数数组进行线性时间复杂度的排序。文章还探讨了计数排序的优化方法,包括考虑数列的最小值以减少空间浪费,并解决了相同元素排序的问题,确保排序稳定性。同时,指出了计数排序的局限性,如适用范围和元素类型限制。
摘要由CSDN通过智能技术生成

线性时间的排序之计数排序

回顾之前的排序:
冒泡排序:在一个数组中,如果左边的大于右边的,则它两互相交换位置。

堆排序:同样也是交换元素的位置
有一些特殊得排序并不基于元素比较,如计数排序、桶排序、基数排序。。

一、初始计数排序
假设数组中有20个随机数,取值范围为0~10,要求用最快得速度把这20 个整数从小到大进行排序。

根据这个有限的范围建立一个长度为11的数组,数组下标从0开始。元素初始值为0.
假设值为:

9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9,7,9

对这个无序的随机数列进行遍历,每一个整数按照其值对号入座,同时,对应数组下标的元素进行加1操作。
最终根据其值的大小,对应数组中的下标位置,并加1.。其意思就是,给了一个长度为11的数组。每一个初始都是0.然后遍历数组时根据值的大小,对应在数组中找到位置,并加一次(出现了一次就加1,依此类推,出现几次就在对应的位置加几次。)

则最终得到下面的数组

1 ,2,1,3,2,2,1,2,1,4,1

0,1,2,3,4,5,6,7,8,9,10

第一排是对应下面的值出现过的次数。这样看就明白了。

此时,有了这个统计结果。我们就遍历整个数字组。输出数组元素的下标值,元素值是几,就输出几次。
比如:0出现了1次,第一个就是0,1在第一排显示的是2,则就遍历两次,就是出现了两次1,以此类推:

0,1,1,2,3,3,3,4,4,5,5,6,7,7,8,9,9,9,9,10

看,这样是不是就给排序了。。亲手写写还是很容易懂得,光看真的不如动手一画。

此时输出的数列还是有序的。它适用于一定范围内的整数排序,在值不是很大的情况下性能还是很快的。

代码:




public class quikSort {
    public static int[] countSort(int[] array){
        //1,得到数列的最大值
        int max =array[0];
        for (int i = 1; i <array.length ; i++) {
            if (array[i]>max){
                max=array[i];

            }
        }
        //2,根据得到的最大值确定统计数组的长度
        int[] countArray = new int [max+1];
        //3,遍历梳理,填充统计数组
        for (int i = 0; i <array.length; i++) {
            countArray[array[i]]++;
        }
        //4,遍历统计数组,输出结果
        int index = 0;
        int[] sortedArray = new int[array.length];
        for (int i = 0; i <countArray.length ; i++) {
            for (int j = 0; j <countArray[i] ; j++) {
                sortedArray[index++]=i;
            }
        }
        return sortedArray;
    }

    public static void main(String[] args) {
        int[] array=new int[]{4,4,6,5,3,2,8,1,7,5,6,0,10};
        int[] sortedArray =countSort(array);
        System.out.println(Arrays.toString(sortedArray));
    }
}

结果:
在这里插入图片描述

代码开头求数列的最大整数值max.后面创建的统计数组countArray,长度是max+1,以此保证数组的最后一个下标是max.

二,计数排序的优化
以上只以数列的最大值来决定统计数组的长度并不严谨。万一值的大小并不是从0开始,从80开始到99,那么创建一个数组长度为100 的数组,80以前的空间岂不是被浪费了。

解决办法;

不以输入数列的最大值+1作为统计数组的长度,而是以数列最大值-最小值+1作为统计数组的长度。
同时,数列的最小值作为一个偏移量,用于计算整数在统计数组中的下标。

以刚才的数组为例,统计数组的长度为99-90+1=10,偏移量等于数列的最小值80.
对于第一个整数,对应得统计数组下标就是(假设第一个是95),则下标就是95-90=5,则在第5个位置。

上述方法只是给一个整数进行了排序并且没有浪费空间,但是用到实际项目应用中,还是有以写缺陷,假设对一个小学期末成绩做大小排序,出现了两个一摸一样的分数,99.但是这样排序的话并不是到底是小明,还是小张。此时又改怎么解决呢?

简要说明:就是从统计数组的第 2 给 元素开始,每一个元素都加上前面所以元素之和。这样加的目的是让统计数组存储的元素值,等于相应整数的最终排序位置的序号,例如下标是9的元素值为5,代表原始数列的整数9,最终排序在第5位。
接下来创建一个新的数组,长度和输入数列一致,然后从后向前遍历输入数列。

代码说明:



public class quikSort2 {
    public static int[] countSort(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];
            }
        }
        int d = max-min;
        //2,创建统计数组并统计对应元素的个数
        int[] countArray = new int [d+1];
        for (int i = 0; i <array.length; i++) {
            countArray[array[i]-min]++;
        }
        //3,统计数组做变形,后面的元素都等于前面元素之和
        for (int i = 1; i <countArray.length ; i++) {
            countArray[i]+= countArray[i-1];
        }
        //4,倒叙遍历原始数列,从统计数组找到正确位置,输出到结果数组
        int[] sortedArray = new int[array.length];
        for (int i = array.length-1; i >=0 ; i--) {
           sortedArray[countArray[array[i]-min]-1]=array[i];
           countArray[array[i]-=min]--;
        }
        return sortedArray;
    }

    public static void main(String[] args) {
        int[] array=new int[]{95,94,91,98,99,90,99,93,91,92};
        int[] sortedArray =countSort(array);
        System.out.println(Arrays.toString(sortedArray));
    }
}

结果:
在这里插入图片描述

优化后的计数排序属于稳定排序,但是也有它的局限性。
1,当数列最大和最小值差距过大时,并不适合用计数排序。
例如给出20个随机整数,范围在0到一亿之间,这时如果用计数排序,需要创建的长度过大,严重浪费空间。时间复杂度也会随之升高。
2,当数列元素不是整数时,也不适合用计数排序。
比如带小数点的,也无法排序。

额。。。。。消化消化再继续。。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值