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

news2024/12/22 20:01:43
过去心不可得,现在心不可得,未来心不可得

目录在这里

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

楔子

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

但对我来说,稍显遗憾的是,书籍代码是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. 占用空间。空间复杂度为O(m+n),因为桶的长度取决于元素取值范围,元素取值范围越大,越占用空间。
    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.coloradmin.cn/o/1409567.html

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

相关文章

AR 自回归模型

文章目录 总的代码ADF 检验(是否平稳)差分操作拟合AR 模型预测可视化总的代码 import pandas as pd import numpy as np import matplotlib.pyplot as plt from statsmodels.tsa.ar_model import AutoReg from statsmodels.tsa.stattools import adfuller# 生成一个示例时间序…

【开源】基于JAVA语言的假日旅社管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统介绍2.2 QA 问答 三、系统展示四、核心代码4.1 查询民宿4.2 新增民宿评论4.3 查询民宿新闻4.4 新建民宿预订单4.5 查询我的民宿预订单 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的假日旅社…

Java-HashMap如何找落点

顾名思义&#xff0c;HashMap采用的是哈希方式来找落点&#xff0c;通过数据的某些特征&#xff0c;计算出一个哈希值&#xff0c;然后用哈希值与节点建立映射关系&#xff0c;从而确定这个数据应该在哪个节点上&#xff0c;下图是一个具有16个节点的分布式集群&#xff0c;本文…

JVM篇--垃圾回收器高频面试题

1 你知道哪几种垃圾收集器&#xff0c;各自的优缺点是啥&#xff0c;重点讲下cms和G1&#xff0c;包括原理&#xff0c;流程&#xff0c;优缺点&#xff1f; 1&#xff09;首先简单介绍下 有以下这些垃圾回收器 Serial收集器&#xff1a; 单线程的收集器&#xff0c;收集垃圾时…

【K8S 云原生】K8S的图形化工具——Rancher

目录 一、rancher概述 1、rancher概念 2、rancher和K8S的区别&#xff1a; 二、实验 1、安装部署 2、给集群添加监控&#xff1a; 3、创建命名空间&#xff1a; 4、创建deployment&#xff1a; 5、创建service&#xff1a; 6、创建ingress&#xff1a; 7、创建hpa 8…

redis—Set集合

目录 前言 1.常见命令 2.使用场景 前言 集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中1)元素之间是无序的2)元素不允许重复&#xff0c;如图2-24所示。一个集合中最多可以存储22 - 1个元素。Redis 除了支持集合内的增删查改操…

Android SeekBar 进度条圆角

先看下效果图&#xff1a; 之前&#xff1a; 优化后&#xff1a; 之前的不是圆角是clip切割导致的 全代码&#xff1a; <SeekBarandroid:layout_width"188dp"android:layout_height"wrap_content"android:background"null"android:focusa…

微认证 openEuler社区开源贡献实践

文章目录 1. 开源与开源社区2. openEuler 社区概述3.参与openEuler社区贡献4.openEuler软件包开发Linux软件管理——源码编译 1. 开源与开源社区 Richard Matthew Stallman&#xff0c;1983年9月推出GNU项目&#xff0c;并发起自由软件运动(free software movement或free/open…

【并发】什么是 Future?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 关键特性和操作包括&#xff1a; 提交任务&#xff1a; 查询完成状态&#xff1a; 等待结果&#xff1a; 取消任务&#xff1a…

Vue实现图片预览,侧边栏懒加载,不用任何插件,简单好用

实现样式 需求 实现PDF上传预览&#xff0c;并且不能下载 第一次实现&#xff1a;用vue-pdf&#xff0c;将上传的文件用base64传给前端展示 问题&#xff1a; 水印第一次加载有后面又没有了。当上传大的pdf文件后&#xff0c;前端获取和渲染又长又慢&#xff0c;甚至不能用 修…

Windows下网络编程(win32API+VS2022)

一、开发环境 我这里介绍下我用的环境安装过程。 所有版本的VS都可以的。 我当前环境是在Windows下&#xff0c;IDE用的是地表最强IDE VS2022。 下载地址&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/ 因为我这里只需要用到C和C语言编程&#xff0c;那…

SRC实战 | 小白SRC找到的第一个SQL注入

本文由掌控安全学院 - zbs投稿 一、漏洞说明 xxxxx公司后台存在SQL注入&#xff0c;后端数据库为Mysql 【显错位2&#xff0c;4&#xff0c;6】 漏洞已提交平台&#xff0c;后台的开发商提供给了很多公司&#xff0c;搜一下资产就有很多公司都没有修复该漏洞。 二、漏洞挖掘…

Java Web(四)--JavaScript

介绍 JavaScript 教程 JavaScript 能改变 HTML 内容&#xff0c;能改变 HTML 属性&#xff0c;能改变 HTML 样式 (CSS)&#xff0c;能完成页面的数据验证&#xff1b; JS 需要运行浏览器来解析执行JavaScript 代码&#xff1b; JS 是 Netscape 网景公司的产品&#xf…

Git搭建

文件格式 <VirtuaHost * 80> nginx </virtualHost> pache xml server {} nginx conf格式 [xx] 配置内容 代码开发中版本控制,项目代码编译构建,项目版本迭代全流程 命令300条 Hospital Information System 开发语言分类: 编译型: C nginx ma…

SSL证书 DV、OV、EV等级的证书适用群体

DV&#xff08;Domain Validation&#xff0c;域名验证&#xff09;证书 特点&#xff1a;DV证书是最基础的SSL/TLS证书类型&#xff0c;仅验证申请证书的实体是否对该域名有控制权。验证过程相对简单快速&#xff0c;通常只需要验证域名的所有权即可。 适用人群&#xff1a;…

蓝桥杯备战——2.矩阵键盘

1.分析原理图 由上图可以看到若J5跳线帽接地&#xff0c;就S4~S7就可以当做四路独立按键&#xff0c;若接到P44&#xff0c;则就是4*4的矩阵键盘。 2.独立按键处理 相对传统的按键延时消抖方案&#xff0c;这里我采用更高效&#xff0c;更经典&#xff0c;更偏向产品级应用的…

2016年认证杯SPSSPRO杯数学建模B题(第一阶段)低分辨率下看世界全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 B题 低分辨率下看世界 原题再现&#xff1a; 数码摄像技术被广泛使用于多种场合中。有时由于客观条件的限制&#xff0c;拍摄设备只能在较低的分辨率下成像。为简单起见&#xff0c;我们只考虑单色成像。假设成像的分辨率为 32 64&#xff0c…

一文读懂mysql的锁

提起mysql的锁&#xff0c;你是否会似懂非懂&#xff0c;最常听人提起的就是乐观锁&#xff0c;悲观锁、排他锁、共享锁 悲观锁是用 select c form T for update然后等待提交实现的&#xff0c;但是你知道吗&#xff0c;其实排他锁和悲观锁其实是一回事&#xff01;&#xff0…

vue常用指令(v-if)

一、v-if 指令 作用: 根据表达值的真假,切换元素的显示和隐藏( 操纵dom 元素 ) 二、代码演示 1、v-if 设置条件&#xff0c;添加按键修改状态 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta na…

12. banner 定制

1. 简介 Spring Boot 启动时默认会显示以下 LOGO&#xff1a; . ____ _ __ _ _ /\ / ’ __ _ () __ __ _ \ \ \ ( ( )__ | _ | | | ’ / | \ \ \ \/ )| |)| | | | | || (| | ) ) ) ) ’ || .__|| ||| |_, | / / / / |||///// :: Spring Boot :: (v2.1.1.RELEASE) 实际上&am…