数据结构---计数排序

news2024/11/17 19:34:42

计数排序

  • 计数排序
    • JAVA实现
  • 计数排序优化
    • 存在的问题1:
    • 存在的问题2
    • JAVA实现
  • 局限性

冒泡排序,还是快速排序,都是基于元素之间的比较来进行排序
有一些特殊的排序并不基于元素比较,如计数排序、桶排序、基数排序。

计数排序:利用数组下标来确定元素的正确位置的

线性时间排序算法:

  1. 计数排序
  2. 桶排序

计数排序

在这里插入图片描述
遍历数组,记录每个数字出现的次数
在这里插入图片描述
该数组中每一个下标位置的值代表数列中对应整数出现的次数。

最后:直接遍历数组,输出数组元素的下标值,元素的值是几,就输出几次。
在这里插入图片描述

适用范围:它适用于一定范围内的整数排序。在取值范围不是很大的情况下,

JAVA实现

package mysort.countingSort;

import java.util.Arrays;

public class countingSort {
    public static int[] countSort(int[] array){
        //取数列的最大值
        int max = array[0];
        for (int i = 1;i<array.length;i++){
            if(array[i]>max){
                max = array[i];
            }
        }
        //根据数组最大值确定统计数组countArray的长度
        //默认条件是:数组元素非负
        int[] countArray = new int[max+1];
        //遍历数组,统计个数,并填充统计数组countArray
        for (int i=0;i<array.length;i++){
            countArray[array[i]]++;
        }

        //遍历统计数组countArray,输出结果
        //index是记录sortedArray数组填充到哪的一个下标(每次填充,就加1)
        int index = 0;
        //创建一个和array一样长度的数组,用于存放最后的输出结果
        int[] sortedArray = new int[array.length];
        //外层循环是对countArray的每一个位置进行遍历
        //内层循环是针对countArray的一个位置,
        // 这个位置值是i
        // 对应的元素个数是countArray[i]
        //把他存入sortedArray
        for (int i=0;i<countArray.length;i++){
            for (int j=0;j<countArray[i];j++){
                sortedArray[index]=i;
                index++;
            }
        }
        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[] sortarrray = countSort(array);
        System.out.println(Arrays.toString(sortarrray));
    }
}

在这里插入图片描述
在这里插入图片描述

计数排序优化

存在的问题1:

我们只以数列的最大值来决定统计数组的长度,其实并不严谨。
解决方案:只要不再以输入数列的最大值+1作为统计数组的长度,而是以数列最大值-最小值+1作为统计数组的长度即可。
数列的最小值作为一个偏移量,用于计算整数在统计数组中的下标。

在这里插入图片描述
数组的长度为99-90+1=10
第1个整数95,对应的统计数组下标是95-90 = 5

存在的问题2

给出一个学生成绩表,要求按成绩从低到高进行排序,如果成绩相同,则遵循原表固有顺序。
注意:这里的重点条件是:如果成绩相同,则遵循原表固有顺序。
在这里插入图片描述
在这里插入图片描述
将统计数组变形为:
在这里插入图片描述
变形规则是:从统计数组的第2个元素开始,每一个元素都加上前面所有元素之和。
这样相加的目的,是让统计数组存储的元素值,等于相应整数的最终排序位置的序号。

第1步,遍历成绩表最后一行的小绿同学的成绩。
小绿的成绩是95分,找到countArray下标是5的元素,值是4,代表小绿的成绩排名位置在第4位。
同时,给countArray下标是5的元素值减1,从4变成3,代表下次再遇到95分的成绩时,最终排名是第3。(小红就是第三位)
这样就达到了:如果成绩相同,则遵循原表固有顺序的目的。
在这里插入图片描述

这样一来,同样是95分的小红和小绿就能够清楚地排出顺序了,也正因为此,优化版本的计数排序属于稳定排序。

JAVA实现

package mysort.countingSort;

import java.util.Arrays;

public class countingSort2 {
    public static int[] countSort(int[] array){
        //1.得到数列的最大值和最小值,并算出差值d
        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];
        //3统计对应元素的个数 (array[i]-min就是array数组中元素的偏移地址)
        for (int i=0;i<array.length;i++){
            countArray[array[i]-min]++;
        }
        System.out.println("原始的计数数组为"+Arrays.toString(countArray));
        //统计数组做变形,后面的元素等于前面的元素之和
        for (int i =1;i<countArray.length;i++){
            countArray[i]+=countArray[i-1];
        }
        System.out.println("变形后的计数数组为"+Arrays.toString(countArray));
        //4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
        //countArray[array[i]-min]-1其中减去1的原因是在sortedArray数组中,下标从0开始。。
        //就以95小绿为例子
        int[]sortedArray = new int[array.length];
        for (int i=array.length-1;i>=0;i--){
            sortedArray[countArray[array[i]-min]-1]=array[i];
            //在将countArray中存储的数字(位置)减去1
            countArray[array[i]-min]--;
        }
        return sortedArray;
    }

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

在这里插入图片描述

在这里插入图片描述

时间复杂度:O(n+m)。代码第1、2、4步都涉及遍历原始数列,运算量都是n,第3步遍历统计数列,运算量是m,所以总体运算量是3n+m ,用大O表示法得去掉系数。

空间复杂度:只考虑统计数组大小的话,空间复杂度是O(m)。

局限性

  1. 当数列最大和最小值差距过大时,并不适合用计数排序。
  2. 当数列元素不是整数时,也不适合用计数排序。

解决方案:桶排序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

0. Arthas的基本安装和使用

我们慢慢寻找&#xff0c;直到找到我们的方向。 选择了方向&#xff0c;便一往无前。 我们爱那少年&#xff0c;一如爱我们自己。 Arthas 的简介 Arthas 的官方文档: https://arthas.aliyun.com/doc/ Arthas的官方命令文档: https://arthas.aliyun.com/doc/advanced-use.html …

数据结构-难点代码突破(C++实现图广度优先遍历,深度优先遍历,广度/深度优先遍历生成树和森林,广度优先遍历求单源非带权图两点最短路径)

注意&#xff1a;为了简便起见&#xff0c;这里采用邻接矩阵的方式储存图的边信息 文章目录1.邻接矩阵图的广度优先遍历单源非带权图的两点最短路径2. 邻接矩阵图的深度优先遍历3. 广度/深度优先遍历生成树和森林深度优先生成树与森林广度优先遍历生成树与森林图的遍历是指从图…

Compose回忆童年 - 手拉灯绳-开灯/关灯

一、前言 偶然间想到小时候顺着那白色开关垂下来的灯绳&#xff0c;拉一下“咔哒”一声&#xff0c;再拉一下又是“咔哒”一声。当时年龄小感觉新奇总是把灯开了关又关了开的拉着玩&#xff0c;以至于好几次拉坏了开关灯绳。 今天我们在手机上做一个拉不坏的灯绳&#x1f604…

毕业四年,我当初是如何走上编程这条路的!

感概万千&#xff0c;毕业已达4年之久。 想起在大学时期学习编程的事情&#xff0c;感觉很有意义&#xff0c;在此记录回顾一下。 希望自己初心未变&#xff0c;勇往向前 现状与过去 20210706 目前的我是在天津一家公司做前端开发&#xff0c;主要用Python。 从毕业实习到…

入门:容器工作机制概述

我们先来看看Docker的整体架构&#xff1a; 实际上分为三个部分&#xff1a; Docker 客户端&#xff1a;也就是我们之前使用的docker命令&#xff0c;都是在客户端上执行的&#xff0c;操作会发送到服务端上处理。 Docker 服务端&#xff1a;服务端就是启动容器的主体了&#x…

Java项目:SSM网上超市购物商城管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目分为前后台&#xff0c;分为普通用户、管理员两种角色。前台普通用户登录&#xff0c;后台管理员登录&#xff1b; 管理员角色包含以下功…

毕业设计 单片机温湿度环境检测仪 - stm32 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理5 部分核心代码6 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长…

Dynamic RSA System 设计与实现

一、背景 在实现了静态的加解密工具后&#xff0c;感觉不够灵活&#xff0c;想设计一个动态生成 RSA KeyPair 的中间系统&#xff0c;暂且称为 Dynamic RSA System&#xff0c;以达到自动化维护信安高墙的效果。 加解密和签名校验工具_余衫马的博客-CSDN博客_校验和工具RSA加…

Zero-sho原先的升级版:hourglass网络:U-Net

ZMFF: Zero-shot multi-focus image fusion &#xff08;ZMFF: Zero-shot 多聚焦图像融合&#xff09; &#xff08;本论文的先导片&#xff1a;ZERO-SHOT MULTI-FOCUS IMAGE FUSION&#xff09; 这是我们之前的扩展工作。在ZMFF,我们做一些改动和改进相比原来的框架。首先&…

数学英语不好,新手学编程难吗?适合学Python吗?

英语不好&#xff0c;上学时考试从来没有超越40分。 数学也不可&#xff0c;很多的东西都还给老师了。 我还能学习编程吗&#xff1f;&#xff1f;&#xff1f; 刚开始学习的时分&#xff0c;这个问题深深的困扰着我。以致于我其时报培训班之前犹疑了很长很长时刻。 由于在我…

[C语言数据结构]万字长文带你学习八大排序

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;数据结构 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客讲解八大排序&#xff0c;及其优化 文章目录排序Ⅰ插入排序&…

配置SSH Keys到github,实现本地操作远程仓库的权限

文章目录第1步&#xff1a;创建SSH Key第2步&#xff1a;检查是否纯正.ssh目录第3步&#xff1a;复制id_rsa.pub的内容第4步&#xff1a;在你的github页面上配置SSH key第5步&#xff1a;验证是否可连接第1步&#xff1a;创建SSH Key 在用户根目录下&#xff0c;打开命令&…

非零基础自学Golang 第10章 错误处理 10.5 Go语言错误的应用 10.6 小结 10.7 知识拓展

非零基础自学Golang 文章目录非零基础自学Golang第10章 错误处理10.5 Go语言错误的应用10.6 小结10.7 知识拓展10.7.1 error接口的应用第10章 错误处理 10.5 Go语言错误的应用 10.4.2小节中的panic()和recover()虽然能模拟其他语言的异常机制&#xff0c;但是并不建议在Go语言…

广州特耐苏-广州风淋通道构造及特点

风淋通道构造及风淋通道特点-广州特耐苏-广州风淋通道-广州风淋通道规格-广州风淋通道置量-广州风淋通道价格-特耐苏拥有*的数控加工设备&#xff0c;技术力量雄厚&#xff0c;专业生产自动化/风淋室货淋室、 >>采用更适合洁净室原理的圆弧转角; >>系统自动控制运…

密码技术扫盲:非对称加密

个人博客 密码技术扫盲&#xff1a;对称加密&#x1f3af; 密码技术扫盲&#xff1a;非对称加密密码技术扫盲&#xff1a;认证 在上一篇对称加密的介绍中&#xff0c;我们了解到对明文的加密需要使用到密钥&#xff0c;而解密时也必须用到同一把密钥&#xff0c;也就是说发送…

假如编程是魔法之零基础看得懂的Python入门教程

一、前言 几个月前编写了一份python语言入门的博文&#xff0c;近期重新审阅了一遍发现编写的质量太过随意&#xff0c;可能对于一部分人并不是非常友好&#xff0c;故此重新编写Python语言的零基础教程。 本篇教程将会尽量把一些专业术语给读者讲解清楚&#xff0c;并且让读者…

如何成为一个优秀的Python工程师?

众所周知&#xff0c;Python因其优雅而简洁的语言优势而备受程序员的青睐和追捧。随着人工智能、大数据技术的落地&#xff0c;Python工程师也成为了目前薪资待遇高&#xff0c;发展前景好的热门岗位。虽然&#xff0c;Python入门简单&#xff0c;对初学者友好&#xff0c;但是…

52 如何 尽可能的减少 自定义ClassLoader 造成的影响

前言 // 呵呵 很快又该总结 2022 了, 希望这一年也能总结出很多收获 接着 java.lang.Class/java.lang.ClassLoader/InstanceKlass/ClassloaderData 的卸载 可以先看一下 这一篇文章, 明确一下 上下文 这里 主要说的是 如果我们的场景中存在自定义的 classloader 的情况…

Flask + echarts 轻松解决 nginx 日志可视化

最近&#xff0c;线上的业务系统不太稳定&#xff0c;需要分析下访问情况&#xff0c;能拿到的数据只有 nginx 服务器的访问日志&#xff0c;不过难不倒我&#xff0c;用合适的工具&#xff0c;分分钟做出图形化展示&#xff0c;看看怎么做的吧 思路 nginx 访问日志&#xff…

9 CPP结构体注意事项

注意&#xff1a; 1 结构名是标识符 2 结构体的成员可以是任意数据类型 3 定义结构体描述的代码可以放在程序的人和地方&#xff0c;一般放在main函数的上面或头文件中。 4 结构体成员可以用C的类&#xff08;如string&#xff09;&#xff0c;但是不提倡。 5 在C中&#…