Java玩转《啊哈算法》排序之桶排序

过去心不可得,现在心不可得,未来心不可得

目录在这里

  • 楔子
  • 代码地址
  • 桶排序
  • 代码
    • 核心部分
      • 优缺点
    • 完整代码
    • 演示
  • 升级版
    • 核心代码
    • 完整代码
    • 演示

楔子

大家好!本人最近看了下《啊哈算法》,写的确实不错,生动形象又有趣(我没收钱,确实如此 )。

但对我来说,稍显遗憾的是,书籍代码是c语言,而不是本人常用的Java。

那就弥补遗憾,说干就干,把这本书的示例语言用java给翻译一遍!!!

于是就有了本篇博客,当然这只是第一篇,主要是讲解桶排序。
在这里插入图片描述

没有买纸质书的童鞋也甭担心,电子版的下载链接已经放到下方了,自己下载去吧!!!

链接:https://pan.baidu.com/s/1imxiElcCorw2F-HJEnB-PA?pwd=jmgs
提取码:jmgs

不过还是建议有条件的同学可以买下纸质书,尊重一下作者的劳动成果。

代码地址

本文代码已开源:

git clone https://gitee.com/guqueyue/my-blog-demo.git

请切换到gitee分支,

然后查看aHaAlgorithm模块下的src/main/java/com/guqueyue/aHaAlgorithm/chapter_1_Sort即可!

桶排序

算法学习千千万,排序是块敲门砖!!!

国内算法学习似乎有个不成文的规定,想学算法,先学排序。而桶排序可以说是排序算法中最简单的算法了。

在这里插入图片描述

桶排序的核心原理非常简单:

遍历需要排序的元素集合,用一个数组表示。数组的一个个连续的空间作为一个个桶,索引为元素,而索引对应的值为元素个数。

相当于把元素放到对应的一个一个桶里面,所以叫桶排序。
在这里插入图片描述

而因为数组的索引是连续的,所以遍历数组索引就能得到一个升序的元素集合。如果索引对应的值为0,说明该元素不存在。

代码

核心部分

	/*** @Description 桶排序* @Param [scoreArr]* @return int[]**/private static int[] bucketSort(int[] scoreArr) {// 11为数据范围的大小int[] bucket = new int[11];// 用于返回排序后的数组int[] result = new int[scoreArr.length];// 入桶,计数for (int num : scoreArr) {bucket[num]++;}// 根据桶的索引以及计数的次数,生成排序后的数组 - 如果需要降序,倒序遍历数组即可int k = 0;for (int i = 0; i < bucket.length; i++) { // 遍历每个桶for (int j = 0; j < bucket[i]; j++) { // 遍历桶里面的元素result[k++] = i;}}return result;}

优缺点

通过上文的讲解以及核心代码,我们不难得出桶排序具有以下的优缺点:

  • 优点:
    1. 简单
    2. 速度快。时间复杂度为:O(m+n), 其中m为排序数组的大小,n为桶的大小。
  • 缺点:
    1. 占用空间。因为桶的长度取决于元素的取值范围,元素的取值范围越大,越占用空间。
    2. 有使用局限,只能对整数进行排序。若元素中存在小数无法使用桶排序,因为数组的索引不能为小数。

完整代码

package com.guqueyue.aHaAlgorithm.chapter_1_Sort;import java.util.Arrays;
import java.util.Scanner;/*** @Author: guqueyue* @Description: 桶排序* @Date: 2024/1/8**/
public class BucketSort {public static void main(String[] args) {// 获取分数数组int[] scoreArr = getScoreArr();System.out.println("输入的数组为: " + Arrays.toString(scoreArr));// 桶排序int[] result = bucketSort(scoreArr);System.out.println("排序后:" + Arrays.toString(result));}/*** @Description 桶排序* @Param [scoreArr]* @return int[]**/private static int[] bucketSort(int[] scoreArr) {// 11为数据范围的大小int[] bucket = new int[11];// 用于返回排序后的数组int[] result = new int[scoreArr.length];// 入桶,计数for (int num : scoreArr) {bucket[num]++;}// 根据桶的索引以及计数的次数,生成排序后的数组 - 如果需要降序,倒序遍历数组即可int k = 0;for (int i = 0; i < bucket.length; i++) { // 遍历每个桶for (int j = 0; j < bucket[i]; j++) { // 遍历桶里面的元素result[k++] = i;}}return result;}/*** @Description 获取分数数组* @Param []* @return int[]**/private static int[] getScoreArr() {Scanner scanner = new Scanner(System.in);System.out.print("请输入数组长度:");int n = scanner.nextInt();int[] scoreArr = new int[n];for (int i = 0; i < n; i++) {System.out.printf("请输入第%d个数(范围:0-10),然后按回车: ", i+1);scoreArr[i] = scanner.nextInt();}return scoreArr;}
}

演示

运行代码,控制台输入可得:
在这里插入图片描述

升级版

正如作者所说,上文演示的只是一个简易版的桶排序算法。

那如果需要输入多个学生的姓名和分数,再根据学生的分数排名由高到低输出学生的姓名,这样要怎么做呢?

作者这里并没有给出答案,我们来扩展一下,首先创建一个学生类:

package com.guqueyue.aHaAlgorithm.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @Author: guqueyue* @Description: 学生类* @Date: 2024/1/9**/
//lombok插件的注解
@Data // 若未使用lombok插件,请自行生成getter、setter以及toString方法
@NoArgsConstructor // 若未使用lombok插件,请自行生成无参构造方法
@AllArgsConstructor // 若未使用lombok插件,请自行生成有参构造方法
public class Student {private String name; // 姓名private Integer score; // 分数
}

核心代码

同理,我们使用桶排序,得到一个通过分数降序排序的学生数组:

	/*** @Description 桶排序 - 通过分数排序学生数组* @Param [scoreArr]* @return com.guqueyue.aHaAlgorithm.entity.Student[]**/private static Student[] bucketSort(Student[] scoreArr) {Student[] result = new Student[scoreArr.length];// 桶排序,将分数入桶int[] bucket = new int[101];for (Student student : scoreArr) {bucket[student.getScore()]++;}int k = 0;for (int i = 100; i >= 0; i--) { // 倒序遍历桶if (bucket[i] > 0) {for (Student student : scoreArr) { // 遍历学生数组,将符合当前桶的分数的学生放入数组if (student.getScore() == i) {result[k++] = student;}}}}return result;}

完整代码

package com.guqueyue.aHaAlgorithm.chapter_1_Sort;import com.guqueyue.aHaAlgorithm.entity.Student;import java.util.*;/*** @Author: guqueyue* @Description: 桶排序 - 通过分数排序学生数组* @Date: 2024/1/9**/
public class BucketSort2 {public static void main(String[] args) {Student[] scoreArr = getStudentArr(); // 获取学生数组System.out.println("输入的数组为:" + Arrays.toString(scoreArr));Student[] result = bucketSort(scoreArr);System.out.println("排序后的数组为: " + Arrays.toString(result));System.out.print("学生排名为: ");for (Student student : result) {System.out.print(student.getName() + " ");}System.out.println();}/*** @Description 桶排序 - 通过分数排序学生数组* @Param [scoreArr]* @return com.guqueyue.aHaAlgorithm.entity.Student[]**/private static Student[] bucketSort(Student[] scoreArr) {Student[] result = new Student[scoreArr.length];// 桶排序,将分数入桶int[] bucket = new int[101];for (Student student : scoreArr) {bucket[student.getScore()]++;}int k = 0;for (int i = 100; i >= 0; i--) { // 倒序遍历桶if (bucket[i] > 0) {for (Student student : scoreArr) { // 遍历学生数组,将符合当前桶的分数的学生放入数组if (student.getScore() == i) {result[k++] = student;}}}}return result;}/*** @Description 桶排序优化版 - 通过分数排序学生数组* @Param [scoreArr]* @return com.guqueyue.aHaAlgorithm.entity.Student[]**/private static Student[] bucketSort2(Student[] scoreArr) {// 1.构建 分数 -> 人名集合 映射集Map<Integer, List<Student>> dict = new HashMap<>();for (Student student : scoreArr) {Integer score = student.getScore();List<Student> studentList = new ArrayList<>();if (dict.containsKey(score)) {studentList = dict.get(score);}studentList.add(student);dict.put(score, studentList);}Student[] result = new Student[scoreArr.length];// 桶排序int[] bucket = new int[101];for (Student student : scoreArr) {bucket[student.getScore()]++;}int k = 0;for (int i = 100; i >= 0; i--) {if (bucket[i] > 0) { // 如果有List<Student> students = dict.get(i);if (students != null && students.size() > 0) {for (Student student : students) {result[k++] = student;}}}}return result;}/*** @Description 获取学生数组* @Param []* @return com.guqueyue.aHaAlgorithm.entity.Student[]**/private static Student[] getStudentArr() {Scanner scanner = new Scanner(System.in);System.out.print("请输入学生数量:");int n = scanner.nextInt();Student[] students = new Student[n];for (int i = 0; i < n; i++) {Student student = new Student();System.out.printf("请输入第%d个学生的姓名:", i+1);student.setName(scanner.next());System.out.printf("请输入第%d个学生的分数(0-100):", i+1);student.setScore(scanner.nextInt());students[i] = student;}return students;}
}

演示

运行代码,控制台输入,可得:
在这里插入图片描述

我们下期博客再见!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssh登录失败:connection closed by foreign host

问题1&#xff1a; ssh登录不上&#xff0c;连接上就断掉 inetd.conf显示2277已打开&#xff0c;ip也没有冲突。 但是这两个文件是空的(size 0k)&#xff1a; dropbear_dss_host_key dropbear_rsa_host_key 把/etc/dropbear里面的东西删掉,重新生成秘钥文件&#xff1a; …

如何有效的开展接口自动化测试,一篇足矣

一、简介 接口自动化测试是指使用自动化测试工具和脚本对软件系统中的接口进行测试的过程。其目的是在软件开发过程中&#xff0c;通过对接口的自动化测试来提高测试效率和测试质量&#xff0c;减少人工测试的工作量和测试成本&#xff0c;并且能够快速发现和修复接口错误&…

ChatGPT与生成式AI在教育领域的应用前景光明,但也伴随着挑战

随着ChatGPT和其他生成式AI技术&#xff0c;如GPT-3.5、GPT-4的出现&#xff0c;我们正见证教育领域一场前所未有的变革浪潮。这些技术不仅推动了教育方式的进步&#xff0c;也为学习者带来了全新的机遇和挑战。 NO.1 教育变革的新浪潮 生成式AI技术&#xff0c;特别是ChatGPT…

Database__进阶

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724?spm1000.2115.3001.5343 &#x1f389; 主题&#xff1a; 数据库mysql&#xff08;高级部分&#xff09; ⏱️ 创作时间&#xff1a;2024年01月24…

GPT5?OpenAI 创始人:GPT5 已在训练中,需要更多数据

OpenAI 最近发出征集大规模数据集的呼吁&#xff0c;特别是“今天在互联网上尚未公开轻松获取”的数据集&#xff0c;尤其是长篇写作或任何格式的对话。 GPT-5丨AI浪潮席卷全球&#xff0c;OpenAI 推出GPT-4 后&#xff0c;又于上月26日宣布今年9月、10月将推出GPT-4.5&#xf…

前后置、断言、提取变量、数据库操作功能

前置操作和后置操作都是 API 请求在发送和响应过程中执行的脚本&#xff0c;主要用于在发起 API 请求前和获得响应后完成验证或执行某些操作&#xff0c;目的是为了提高 API 调试和测试的效率&#xff0c;并确保接口的正确性。 前置操作​ 前置操作是在 API 请求之前执行的脚本…

华为产业链之车载激光雷达

一、智能汽车 NOA 加快普及&#xff0c;L3 上路利好智能感知硬件 1、感知层是 ADAS 最重要的一环 先进驾驶辅助系统 &#xff08;ADAS&#xff0c; Advanced driver-assistance system&#xff09;分“感知层、决策层、执行层”三个层级&#xff0c;其中感知层是最重要的一环…

Vue好看的组件库:Element

文章目录 1、什么是Element2、Element快速入门3、Element布局3.1、 Layout 局部3.2、容器布局 1、什么是Element Element&#xff1a;是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库&#xff0c;用于快速构建网页 Element 提供了很多组件&#xff08;组成网页的部件…

【C++干货铺】C++中的四种类型转换

个人主页点击直达&#xff1a;小白不是程序员 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 C语言中的类型转换 为什么C需要四种类型转化 C强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast RTTI C语言中的类型转换 在C语言中&…

在使用springboot框架式的的script无法通过${}来获取值

今天使用springboot框架做项目&#xff0c;想着来实现一下搜索的下拉框回显功能&#xff0c;然后就一直在报错误&#xff0c;关键是报的错误牛头不对马嘴&#xff0c;检查了一下后端代码&#xff0c;发现没什么问题&#xff0c;就把目光聚焦了.jsp页面的代码 <script type&…

MODNet 剪枝再思考: 优化计算量的实验历程分享

目录 1 写在前面 2 模型分析 3 遇到问题 4 探索实验一 4.1 第一部分 4.2 第二部分 Error 1 Error 2 4.3 实验结果 ①参数量与计算量 ②模型大小 ③推理时延 5 探索实验二 5.1 LR Branch 5.2 HR Branch 5.2.1 初步分析 5.2.2 第一部分 enc2x 5.2.3 第二部分 en…

77_组合

描述 给定两个整数 n 和 k&#xff0c;返回范围[1, n]中所有可能的 k 个数的组合。 你可以按任何顺序返回答案。 思路 数组问题 从横向上来看往往有 遍历、滑动窗口、动态规划等思路。但是&#xff0c;其实在遍历这种横向取数过程中&#xff0c;可以根据条件的判断形成树形操作…