【java数据结构】其他非基于比较排序

news2025/1/23 10:25:19

【java数据结构】其他非基于比较排序

  • 一、计数排序
  • 二、基数排序
  • 三、桶排序

博客最后附有整篇博客的全部代码!!!

一、计数排序

场景:集中在某个范围内的一组数据

思路:

  1. 找到这组序列的最大值和最小值,通过最大值和最小值来确定数组大小
  2. 遍历原数组,存储每个元素出现的次数
  3. 将每个元素直接赋值给原数组

时间复杂度:O(N+范围)
空间复杂度:O(范围)
稳定性:稳定

        public static void countingSort(int[] arr) {
            if (arr == null || arr.length == 0) {
                return; // 如果数组为空或长度为0,直接返回
            }

            // 找到数组中的最大值和最小值
            int maxValue = arr[0];
            int minValue = arr[0];
            for (int num : arr) {
                if (num > maxValue) {
                    maxValue = num;
                }
                if (num < minValue) {
                    minValue = num;
                }
            }

            // 计数数组的大小为最大值和最小值的差值加1
            int range = maxValue - minValue + 1;
            int[] countArray = new int[range];

            // 统计每个元素出现的次数
            for (int num : arr) {
                countArray[num - minValue]++;
            }

            int index = 0;
            for(int i = 0; i < countArray.length; i++) {
                while(countArray[i]!=0){
                    arr[index++] = i+minValue;
                    countArray[i]--;
                }
            }
        }

二、基数排序

思想:

基数排序是桶排序的扩展,他的基本思想是:将整数按位切割成不同的数字,然后按每个位数分别比较。
具体做法是:将所有待比较数值统一为同样的位数长度,数位较短的数前边补零。然后,从最低位开始,依次进行一次排序,这样从最低位排序一直到最高位排序完成后,就变成一个有序数列。

(k是最大值的位数, r 是基数,即每一位可能的数字范围(通常是 0 到 9,因此 r=10))
时间复杂度:O(k⋅(n+r)),在 k 是常数时简化为 O(n)
空间复杂度:O(n+r),在 r 是常数时简化为 O(n)
稳定性:稳定的

通过一个实例更好的帮你理解
在这里插入图片描述
给定一组未排序列,首先获取最大值,并且获取最大值的位数(作用:创建数组和循环次数)

 int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        //获取最大值的位数
        int count = 0;
        while(max>=10){
            max=max/10;
            count++;
        }
        count=count+1;

基数排序核心代码就是接下来的两个循环

 //申请所需要的内存空间
        //nums用来存储元素
        int[][] nums = new int[10][arr.length - 1];
        //numsCount是用来计数
        int[] numsCount = new int[10];
        int n = 1;
        for (int h = 0; h < count; h++) {
            for (int i = 0; i < arr.length; i++) {
                int element = arr[i] / n % 10;
                nums[element][numsCount[element]] = arr[i];
                numsCount[element]++;
            }

            int index = 0;
            for (int k = 0; k < numsCount.length; k++) {
                if (numsCount[k] != 0) {
                    for (int i = 0; i < numsCount[k]; i++) {
                        arr[index] = nums[k][i];
                        index++;
                    }
                }
                numsCount[k] = 0;
            }
            n = n * 10;
        }

第一步,先除1再除10取余,得到的数对应到新创建的nums的数组下标,numsCount++,最后再将nums数组中的元素按照顺序取出。

在这里插入图片描述

第二步,先除10再除10取余,按照上面的步骤进行。
在这里插入图片描述
第三步,先除100再除10取余,按照上面的步骤进行。
在这里插入图片描述
这里的步数取决于你最大值的位数,我这里最大值是100,所以有三步。

三、桶排序

思路:

  • 桶排序是计数排序的扩展版本,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过映射函数,将待排序数组中的元素映射到各个对应的桶中,对每个桶中的元素进行排序,最后将非空桶中的元素逐个放入原序列中。

  • 桶排序需要尽量保证元素分散均匀,否则当所有数据集中在同一个桶中时,桶排序失效。

 public static void bucketSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return; // 如果数组为空或长度为0,直接返回
        }

        // 找到数组中的最大值和最小值
        int maxValue = arr[0];
        int minValue = arr[0];
        for (int num : arr) {
            if (num > maxValue) {
                maxValue = num;
            }
            if (num < minValue) {
                minValue = num;
            }
        }
        int bucketCount = (maxValue - minValue) / arr.length + 1;
        //创建桶
        List<List<Integer>> bucket = createBucket(bucketCount);
        //将元素放入桶中
        for (int value : arr) {
            int index = (value - minValue) / arr.length;
            bucket.get(index).add(value);
        }
        //排序并合并
        sortAndMerge(bucket, arr, minValue);
    }

    private static void sortAndMerge(List<List<Integer>> bucket, int[] arr, int minValue) {
        //先对每个桶用计数排序进行排序
        for (int i = 0; i < bucket.size(); i++) {
            countingSort2(bucket.get(i));
        }
        int index = 0;
        for (int i = 0; i < bucket.size(); i++) {
            for (int j = 0; j < bucket.get(i).size(); j++) {
                arr[index++] = bucket.get(i).get(j);
            }
        }
    }

    private static List<List<Integer>> createBucket(int bucketCount) {
        List<List<Integer>> bucket = new ArrayList<List<Integer>>(bucketCount);
        for (int i = 0; i < bucketCount; i++) {
            bucket.add(new ArrayList<>());
        }
        return bucket;
    }

    public static void countingSort2(List<Integer> list) {
        if (list == null || list.size() == 0) {
            return; // 如果链表为空或长度为0,直接返回
        }

        // 找到链表的最大值和最小值
        int maxValue = list.get(0);
        int minValue = list.get(0);
        for (int num : list) {
            if (num > maxValue) {
                maxValue = num;
            }
            if (num < minValue) {
                minValue = num;
            }
        }

        // 计数链表的大小为最大值和最小值的差值加1
        int range = maxValue - minValue + 1;
        int[] countArray = new int[range];

        // 统计每个元素出现的次数
        for (int num : list) {
            countArray[num - minValue]++;
        }
        list.clear();
        int index = 0;
        for (int i = 0; i < countArray.length; i++) {
            while (countArray[i] != 0) {
                list.add(i + minValue);
                countArray[i]--;
            }
        }
    }

桶的大小以及多少是根据自己的需求而定,我这里只是为完成桶排序而随便设置的桶的数量。**int bucketCount = (int) Math.sqrt(array.length);**一般情况下是这样确定桶的数量,这样得出来的数据分布比较均匀。int range = max - min + 1;int bucketCount = range / 10; 这里也可以自己定义桶的范围大小。

此篇博客的全部代码!!!

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

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

相关文章

博客之星2024年度总评选——我的年度创作回顾与总结

2024年&#xff0c;是我在CSDN博客上持续耕耘、不断成长的一年。在此&#xff0c;与大家分享一下我的年度创作回顾与总结。 一、创作成长与突破 在人工智能领域&#xff0c;技术迭代迅速&#xff0c;知识更新频繁。为了保持自己的竞争力&#xff0c;在今年&#xff0c;我始终…

ChromeOS 132 版本更新

ChromeOS 132 版本更新 1. 企业定制化 Chrome Web Store 管理员现在可以使用新设置定制 Chrome Web Store 以适应他们管理的用户&#xff0c;包括以下功能&#xff1a; 添加公司标志添加首页横幅和自定义公告策划扩展集合实施基于类别的控制 这些设置可以通过管理员控制台进…

Golang Gin系列-5:数据模型和数据库

在这篇Gin教程的博客中&#xff0c;我们将探索如何将模型和数据库与Gin框架无缝集成&#xff0c;使你能够构建健壮且可扩展的web应用程序。通过利用流行的库并遵循最佳实践&#xff0c;你将学习如何定义模型、建立数据库连接、执行CRUD操作以及确保基于gin的项目中的数据完整性…

计算机毕业设计hadoop+spark股票基金推荐系统 股票基金预测系统 股票基金可视化系统 股票基金数据分析 股票基金大数据 股票基金爬虫

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

设计模式的艺术-代理模式

结构性模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解代理模式 代理模式&#xff08;Proxy Pattern&#xff09;&#xff1a;给某一个对象提供一个代理&#xff0c;并由代理对象控制对原对象的引用。代理模式是一种对象结构型模式。 代理模式类型较多…

Spring Boot整合Thymeleaf、JDBC Template与MyBatis配置详解

本文将详细介绍如何在Spring Boot项目中整合Thymeleaf模板引擎、JDBC Template和MyBatis&#xff0c;涵盖YAML配置、依赖版本匹配、项目结构设计及代码示例。 一、版本兼容性说明 Spring Boot版本与Java版本对应关系 Spring Boot 2.x&#xff1a;支持Java 8、11&#xff08;推…

【博客之星】2024年度创作成长总结 - 面朝大海 ,春暖花开!

没关系的&#xff0c;大家都会做错选择&#xff0c;会 莫名其妙掉眼泪&#xff0c;走在路上会突然崩溃&#xff0c; 但这并不影响我们去看看晚霞&#xff0c; 再次爱上这个世界。 面朝大海 &#xff0c;春暖花开! about meReviewLife about me 现在我是一名24级计算机类的…

StyleMaster: Stylize Your Video with Artistic Generation and Translation 论文解读

目录 一、概述 二、相关工作 1、图像风格化 2、视频风格化 三、StyleMaster 1、创建对比数据集 2、提取全局描述子 3、局部描述和全局描述结合 4、时间和风格质量的运动适配器 5、Gray Tile ControlNet 四、实验 一、概述 Our StyleMaster demonstrates superior vi…

c++进阶---c++三大特性之一---多态

多态的简单介绍&#xff1a;是一种动态的访问函数&#xff0c;比如&#xff1a;你定义了一个一个人类和一个学生类&#xff0c;当你传入的是学生类的时候&#xff0c;你需要有购物优惠&#xff0c;这种情境下用多态就很适用。 1.简单的多态使用&#xff1a; 1.1构造多态的条件…

安卓程序作为web服务端的技术实现(二):Room 实现数据存储

已经实现web服务器安卓程序作为web服务端的技术实现&#xff1a;AndServer 实现登录权限拦截-CSDN博客 现在需要和正常web项目类似&#xff0c;那么就需要操作数据库 一般web项目都是选择较为重型的数据库如MySQL&#xff0c;SQL server等 这里是安卓项目&#xff0c;我目前…

如何使用Python脚本将本地项目上传到 GitHub

前言 这里我们通过创建一个新的github仓库&#xff0c;来测试我们的脚本能否上传我们本地的项目&#xff0c;并且进行更新。首先你需要先安装 Git&#xff0c;关于这部分我好像没有记录过&#xff0c;这里我搜索看了一下&#xff0c;这篇博客写的Git安装详解应该是比较齐全的&…

Day 15 卡玛笔记

这是基于代码随想录的每日打卡 222. 完全二叉树的节点个数 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#x…

IO进程----进程

进程 什么是进程 进程和程序的区别 概念&#xff1a; 程序&#xff1a;编译好的可执行文件 存放在磁盘上的指令和数据的有序集合&#xff08;文件&#xff09; 程序是静态的&#xff0c;没有任何执行的概念 进程&#xff1a;一个独立的可调度的任务 执行一个程序分配资…

【Postgres_Python】使用python脚本将多个PG数据库合并为一个PG数据库

需要合并的多个PG数据库表个数和结构一致&#xff0c;这里提供一种思路&#xff0c;选择sql语句insert插入的方式进行&#xff0c;即将其他PG数据库的每个表内容插入到一个PG数据库中完成数据库合并 示例代码说明&#xff1a; 选择一个数据库导出表结构为.sql文件&#xff08…

微软预测 AI 2025,AI Agents 重塑工作形式

1月初&#xff0c;微软在官网发布了2025年6大AI预测&#xff0c;分别是&#xff1a;AI模型将变得更加强大和有用、AI Agents将彻底改变工作方式、AI伴侣将支持日常生活、AI资源的利用将更高效、测试与定制是开发AI的关键以及AI将加速科学研究突破。 值得一提的是&#xff0c;微…

《Java核心技术 卷II》获取Web数据提交表单数据

提交表单数据 了解即可&#xff0c;直接上案例 package 第4章网络.post;import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.Reader; import java.net.CookieHandler; import java.net.CookieManager; import java.net.Co…

Spring Boot AOP实现动态数据脱敏

依赖&配置 <!-- Spring Boot AOP起步依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>/*** Author: 说淑人* Date: 2025/1/18 23:03* Desc…

JavaScript —— 变量与运算符

变量与常量 let&#xff1a;用来定义变量&#xff0c;可以只声明不定义&#xff1b; 例如&#xff1a; <script type"module">let a; // 只声明不定义let x 2, name "kitty"; // 定义若干个变量let d { // 定义一个对象&#xff0c;类似于p…

YOLO-cls训练及踩坑记录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、模型训练 二、测试 三、踩坑记录 1、推理时设置的imgsz不生效 方法一&#xff1a; 方法二&#xff1a; 2、Windows下torchvision版本问题导致报错 总结 前…

Android BitmapShader简洁实现马赛克,Kotlin(一)

Android BitmapShader简洁实现马赛克&#xff0c;Kotlin&#xff08;一&#xff09; 这一篇&#xff0c; Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现马赛克效果&#xff0c;Kotlin&#xff08;3&#xff09;-CSDN博客 基于PorterDuffXfermode实现马…