(十一)Java算法:计数排序(详细图解)

news2025/1/21 3:01:26

目录

    • 一、前言
      • 1.1、概念
      • 1.2、算法步骤
    • 二、maven依赖
    • 三、流程解析
      • 3.1、计数流程图
      • 3.2、计数数组变形
      • 3.3、排序过程
    • 四、编码实现

一、前言

1.1、概念

   计数排序:核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数

1.2、算法步骤

  我们大概讲一下算法的步骤。

  1. 找出待排序的数组中的最大元素max和最小元素min
  2. 统计数组中每个元素num出现的次数,存入数组countArraycountArray[num-min]项中
  3. 计数数组变形,对所有的计数累加(从第一项开始countArray[i] = countArray[i] + countArray[i - 1]
  4. 反向填充目标数组arr:从后往前遍历待排序的数列copyArray(拷贝份),由数组元素num计算出对应的计数数组的索引countIndexnum - min,从而推断出numarr的位置为indexcountArray[num-min] - 1,然后num填充到arr[index],最后记得计数数组的值减1,即countArray[countIndex]–

二、maven依赖

pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.6.0</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.14</version>
    </dependency>
</dependencies>

三、流程解析

  假设我们要排序的数据是:8, 10, 12, 9, 8, 12, 8

3.1、计数流程图

  首先我们看看计数统计是什么一回事,计数统计就是把数组中每个元素出现的次数都记录下来,并且能够通过元素找到对应的次数。

在这里插入图片描述

3.2、计数数组变形

  那么计数数组变形又是干啥呢?计数数组变形是从第一项开始,每一项都等于它本身和前一项的和,这样做,得到的值的意思是当前值前面还有多个数字,比如arr[1]=4,表示当前值前面有4-1=3个数字;arr[2]=5,表示当前值前面有5-1=4个数字。
在这里插入图片描述

3.3、排序过程

  最后我们看下具体是怎么排序的,又我们的数组的值推导得到索引,然后从计数数组中找到应该要排的位置,最后插入到对应的数组中,这种方式也是一种稳定的排序方式。
在这里插入图片描述

四、编码实现

  具体的编码实现如下,下面的实现方式也是稳定排序的方式。

/**
 * 计数排序
 *
 * @param arr
 * @return
 */
public static void countingSort(int[] arr) {
    if (arr.length == 0) {
        return;
    }
    // 原数组拷贝一份
    int[] copyArray = Arrays.copyOf(arr, arr.length);
    // 初始化最大最小值
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    // 找出最小值和最大值
    for (int num : copyArray) {
        max = Math.max(max, num);
        min = Math.min(min, num);
    }

    // 新开辟一个数组用于统计每个元素的个数(范围是:最大数-最小数+1)
    int[] countArray = new int[max - min + 1];
    // 增强for循环遍历
    for (int num : copyArray) {
        // 加上最小偏差是为了让最小值索引从0开始,同时可有节省空间,每出现一次数据就加1
        // 真实值+偏差=索引值
        countArray[num - min]++;
    }
    log.info("countArray的初始值:{}", countArray);

    // 获取数组的长度
    int length = countArray.length;
    // 计数数组变形,新元素的值是前面元素累加之和的值
    for (int i = 1; i < length; i++) {
        countArray[i] = countArray[i] + countArray[i - 1];
    }
    log.info("countArray变形后的值:{}", countArray);

    // 遍历拷贝数组中的元素,填充到原数组中去,从后往前遍历
    for (int j = copyArray.length - 1; j >= 0; j--) {
        // 数据对应计数数组的索引
        int countIndex = copyArray[j] - min;
        // 数组的索引获取(获取到的计数数组的值n就是表示当前数据前有n-1个数据,数组从0开始,故当前元素的索引就是n-1)
        int index = countArray[countIndex] - 1;
        // 数组中的值直接赋值给原数组
        arr[index] = copyArray[j];
        // 计数数组中,对应的统计值减1
        countArray[countIndex]--;
        log.info("countArray操作后的值:{}", countArray);
    }
    log.info("排列结果的值:{}", arr);

}

public static void main(String[] args) {
    int[] arr = new int[]{8, 10, 12, 9, 8, 12, 8};
    log.info("要排序的初始化数据:{}", arr);
    //从小到大排序
    countingSort(arr);
    log.info("最后排序后的结果:{}", arr);
}

运行结果:

要排序的初始化数据:[8, 10, 12, 9, 8, 12, 8]
countArray的初始值:[3, 1, 1, 0, 2]
countArray变形后的值:[3, 4, 5, 5, 7]
countArray操作后的值:[2, 4, 5, 5, 7]
countArray操作后的值:[2, 4, 5, 5, 6]
countArray操作后的值:[1, 4, 5, 5, 6]
countArray操作后的值:[1, 3, 5, 5, 6]
countArray操作后的值:[1, 3, 5, 5, 5]
countArray操作后的值:[1, 3, 4, 5, 5]
countArray操作后的值:[0, 3, 4, 5, 5]
排列结果的值:[8, 8, 8, 9, 10, 12, 12]
最后排序后的结果:[8, 8, 8, 9, 10, 12, 12]

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

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

相关文章

[附源码]Python计算机毕业设计Django财务管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

DEJA_VU3D - Cesium功能集 之 087-完美状态栏组件

前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小130个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(尽可能把代码简洁一些)。博文内容…

MacBookPro M2芯片下如何搭建React-Native环境

MacBookPro M2芯片下如何搭建React-Native环境目录软件下载环境配置目录 写在最前&#xff1a;整体流程直接看的rn中文网的搭建开发环境&#xff1a;https://www.react-native.cn/docs/environment-setup 软件下载 1、xcode 2、android studio / vscode 环境配置 1、jdk1.8…

快速上手 TypeScript

快速上手 TypeScript ypeScript 简称 TS &#xff0c;既是一门新语言&#xff0c;也是 JS 的一个超集&#xff0c;它是在 JavaScript 的基础上增加了一套类型系统&#xff0c;它支持所有的 JS 语句&#xff0c;为工程化开发而生&#xff0c;最终在编译的时候去掉类型和特有的语…

Metabase学习教程:仪表盘-2

在仪表板中链接筛选器 链接仪表板中的筛选器&#xff0c;根据另一个筛选器的当前选择限制一个筛选器中可用的选项&#xff08;内容联动&#xff09;。 我们先用一个问题设置一个简单的仪表板。这里的目标是设置一个带有两个链接过滤器的仪表板。每个筛选器根据另一个筛选器的…

PIC单片机4——定时器方波

#include <p18cxxx.h>/*18F系列单片机头文件*/ void PIC18F_High_isr(void);/*中断服务函数声明*/ void PIC18F_Low_isr(void); #pragma code high_vector_section0x8 void high_vector (void) { _asm goto PIC18F_High_isr _endasm/*通过一条跳转指令(汇编指令&am…

设备树覆盖:概念与术语

前面我们讲过设备树相关的东西&#xff0c;其实你应该知道。 但是昨天一个FDT当时我还是有点懵。于是再在android的角度我们来看看这个东西。 1、概览 设备树 (DT) 是用于描述“不可发现”硬件的命名节点和属性构成的一种数据结构。 操作系统&#xff08;例如在 Android 中使…

MyBatis是如何为Dao接口创建实现类的

本文是我的MyBatis源码分析专栏中第三节的一小部分&#xff0c;作为试读部分&#xff0c;详细讲述了MyBatis是如何通过动态代理创建Dao接口的实现类的。 专栏地址&#xff1a;MyBatis源码分析 专栏字数:14w 专栏目录&#xff1a; 文章目录SqlSession.getMapper如何设计的&#…

MySQL----存储过程

目录 一、存储过程的介绍 二、存储过程的基本语法 三、变量 &#xff08;1&#xff09;系统变量 &#xff08;2&#xff09;用户自定义变量 &#xff08;3&#xff09;局部变量 四、存储过程的语法详解 &#xff08;1&#xff09;if判断 &#xff08;3&#xff09;条件…

数据要想管理得好,不得不提开源大数据处理解决方案

在很多企业里&#xff0c;内部数据的管理几乎是一团糟的。在大数据时代的环境中&#xff0c;不少企业急需要提升数据管理的效率&#xff0c;因此想通过一些有利途径来实现这一目的。开源大数据处理解决方案就是其中一个有效途径&#xff0c;是助力企业做好数据管理&#xff0c;…

07 ConfigMap/Secret:怎样配置、定制我的应用

文章目录1. ConfigMap/Secret 介绍1.1 为什么kubernets 要使用应用的配置管理&#xff1f;1.2 有什么类别的配置信息&#xff1f;2. 什么是 ConfigMap&#xff1f;2.1 创建ConfigMap模板文件2.1.1 ConfigMap 怎么生成带data 字段的 模板2.2 创建ConfigMap 对象2.3 查看ConfigMa…

傻白入门芯片设计,一颗芯片的诞生(九)

CPU生产和制造似乎很神秘&#xff0c;技术含量很高。许多对电脑知识略知一二的朋友大多会知道CPU里面最重要的东西就是晶体管了&#xff0c;提高CPU的速度&#xff0c;最重要的一点说白了提高主频并塞入更多的晶体管。由于CPU实在太小&#xff0c;太精密&#xff0c;里面组成了…

Java中的多线程如何理解——精简

目录 线程池处理Runnable任务 线程池处理Callable任务 Executors的工具类构建线程池对象 引言 通过前面的学习&#xff0c;我们已经学会了线程是如何创建的以及线程的常用方法&#xff0c;接下来呢&#xff0c;我们将要深入性了解线程中的知识&#xff0c;主要是线程安全&…

基于PHP+MySQL学生信息管理系统的开发与设计

一直以来我国领导人提倡以人为本的治国方案,而大学是未来人才的培养基地,如何能够更好的对学生信息进行管理,是很多高校一直在研究的一个问题,只有更加科学的对学生信息进行管理,才能够更加积极的培养国家的栋梁之才。 本系统是一个学生信息信息管理系统,为了能够更加灵活的对学…

mysql InnoDB 事务的实现原理

前言 关于mysql的InnoDB存储引擎的关键知识点&#xff0c;已经输出了6篇文章了&#xff0c;但是好像阅读量并不大&#xff0c;可能大家都不太喜欢理论性特别强的东西&#xff1f;或者是这些知识点难度有点高&#xff0c;不太容易被接受&#xff1f;不过&#xff0c;我觉得我分享…

【Java实战】工作中并发处理规范

目录 一、前言 二、并发处理规范 1.【强制】获取单例对象需要保证线程安全&#xff0c;其中的方法也要保证线程安全。 2.【强制】创建线程或线程池时请指定有意义的线程名称&#xff0c;方便出错时回溯。 3.【强制】线程资源必须通过线程池提供&#xff0c;不允许在应用中…

数仓数据同步策略

学习内容一、同步策略一、同步策略 数据同步策略的类型包括&#xff1a;全量同步、增量同步、新增及变化同步、特殊情况 全量表&#xff1a;存储完整的数据增量表&#xff1a;存储新增加的数据新增及变化表&#xff1a;存储新增加的数据和变化的数据特殊表&#xff1a;只需要…

定义自定义指令;inserted()、update()

自定义指令的意义&#xff1a;对普通DOM元素进行底层操作&#xff1b; 作用 &#xff1a;可以获取到底层的dom&#xff0c;拿到想要的节点&#xff0c;从而进行操作&#xff1b; 实际应用&#xff1a;可以通过指令知道什么时候dom创建完成&#xff0c;从而进行依赖dom的库的初…

刷爆力扣之有效的山脉数组

刷爆力扣之有效的山脉数组 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&#x…

超级浏览器的Cookies实现跨境电商防关联

大家有没有过这种感觉&#xff0c;打开电脑或手机&#xff0c;一些你喜欢的视频&#xff0c;总能一下子打到心巴上;心心念念想要下单的东西&#xff0c;总是不停出现在屏幕上诱惑你下单。你以为网络才是最懂你的人&#xff0c;其实是大数据正在研究你的一举一动。而聊到大数据&…