不基于比较的排序:基数排序

news2025/2/9 9:49:30

本篇只是讨论桶排序的具体实现,想了解更多算法内容可以在我的博客里搜,建议大家看看这篇排序算法总结:排序算法总结_鱼跃鹰飞的博客-CSDN博客

 桶排序的原理:

代码:sort1是一个比较二逼的实现方式浪费空间,sort2是一个正式的方法 

package sort;


import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class RadixSort {
    public static void radixSort(int[] arr) {
        int maxBit = getMaxBit(arr);
        sort2(arr, 0, arr.length - 1, maxBit);
    }

    /**
     * 具体的基数排序过程
     * @param arr 排序原始数组
     * @param start 要排序范围开始下标
     * @param end 要排序范围结束下标
     * @param maxBit
     */
    public static void sort(int[] arr, int start, int end, int maxBit) {
        final int bucketSize = 10;
        //先copy一份数据,注意这里的第三个参数要+1,因为是左闭右开
        int[] copy = Arrays.copyOfRange(arr, start, end+1);
        //创建一个Queue数组,长度为10作为桶
        Queue<Integer>[] queues = new LinkedList[bucketSize];
        for(int i = 0; i < bucketSize; i++) {
            queues[i] = new LinkedList();
        }
        for(int digit = 0; digit < maxBit; digit ++) {
            for(int i = start; i <= end; i ++) {
                int bucketNum = digit == 0? copy[i]%10 : (copy[i]/(digit*10))%10;
                //如果是个位的话,直接模10,10位的话,除以digit*10。。。digit*100
                queues[bucketNum].offer(copy[i]);
            }
            //每一次把所有的数放完之后,从桶中倒出,先进去先倒出来(队列实现)
            int curIndex = 0;
            for (int i = start; i <= end; i++) {
                //从0到9挨个取出每个桶里的数据,依次放入copy数组中
                //这就是从桶里倒数据的过程
                for (Queue<Integer> queue : queues) {
                    while (!queue.isEmpty()) {
                        copy[curIndex ++]  = queue.poll();
                    }
                }

            }
        }
        //把排完序的数组复制到原来的数组,如果这个方法是有返回值的,也可以直接返回copy
        for(int i = 0; i < copy.length;i++) {
            arr[i] = copy[i];
        }

    }

    /**
     * 基数排序的省空间的解法
     * @param arr 原始数组
     * @param start 开始下标
     * @param end 结束下标
     * @param maxDigit
     */
    public static void sort2(int[] arr, int start, int end, int maxDigit) {
        final int radixCount = 10;
        //创建一个辅助数组用于中间过程的转换,长度为区间长度
        int[] help = new int[end - start + 1];
        //如果最高位是maxDigit,那从0到maxDigit-1依次进行每一轮的入桶和出桶过程
        for(int digit = 0; digit < maxDigit; digit ++) {
            //统计数组,作为桶使用
            int[] countArr = new int[radixCount];
            //每一轮的入桶操作,countArr[i]代表当前位是i的有多少个数
            for(int i = start; i <= end; i++) {
                int digitNum = getDigitNum(arr[i], digit);
                countArr[digitNum] ++;
            }
            //把countArr改造为前缀和
            //这个循环结束了countArr[i]代表当前位小于等于i的有多少个(i这个数最后的下标是countArr[i]-1)
            for(int i = 0; i < countArr.length; i++) {
                countArr[i] = i == 0? countArr[i] : countArr[i] + countArr[i-1];
            }
            //根据前缀和数组计算当前数字要放的位置
            for(int i = help.length - 1; i >= 0; i --) {
                //取当前位的数
                int digitNum = getDigitNum(arr[i], digit);
                //辅助数组中的countArr[i]代表当前位小于等于i的有多少个,那等于i的最后一个数应该放置在countArr[i]-1位置
                //放完之后等于i的最后没有放元素的还有countArr[i]-1个
                help[--countArr[digitNum]] = arr[i];
            }
            //每一轮拷贝回原数组,方便下次循环用
            for(int i = start; i < end;i++) {
                arr[i] = help[i];
            }
        }


    }

    public static int getDigitNum(int num, int digit) {
        if(digit == 0) return num % 10;
        if(num < Math.pow(10, digit)) {
            return 0;
        }
        int digitNum = num;
        while(digit > 0) {
            digitNum = (digitNum / 10);
            digit --;
        }
        return digitNum%10;
    }

    public static int getMaxBit(int[] arr) {
        int maxBit = 0;
        for(int i = 0; i < arr.length; i++) {
            int curBit = 0;
            int val = arr[i];
            while(val != 0) {
                curBit ++;
                val = val/10;
            }
            maxBit = Math.max(maxBit, curBit);
        }
        return maxBit;
    }

    //判断两个数组每个位置的数是否相等
    public static boolean isEqualsArray(int[] arr1, int[] arr2) {
        if((arr1 == null && arr2 == null) || (arr1 == arr2)) return true;
        if(arr1 == null || arr2 == null || arr1.length != arr2.length)  return false;
        for(int i = 0; i < arr1.length; i++) {
            if(arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int[] arr = {103, 9, 13, 17, 25, 27};
        int[] arr2 = {103, 9, 13, 17, 25, 27};
        int maxBit = getMaxBit(arr);
        System.out.println(maxBit);
        boolean isEquals = isEqualsArray(arr, arr2);
        System.out.println(isEquals);
        radixSort(arr);
        printArr(arr);
        /*int digitNum = getDigitNum(3020,1);
        System.out.println(digitNum);*/

    }

    public static void printArr(int[] arr) {
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

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

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

相关文章

开源数据库Mysql_DBA运维实战 (DML/DQL语句)

DML/DQL DML INSERT 实现数据的 插入 实例&#xff1a; DELETE 实现数据的 删除 实例&#xff1a; UPDATE 实现数据的 更新 实例1&#xff1a; 实例2&#xff1a; 实例3&#xff1a; DQL DML/DQL DML语句 数据库操纵语言&#xff1a; 插入数据INSERT、删除数据DELE…

IT运维:使用数据分析平台监控PowerStore存储(进阶)

概述 本文基于《IT运维&#xff1a;使用鸿鹄监控PowerStore存储》&#xff08;以下简称原文&#xff09;文章进行了优化。主要优化部分包括存储日志进入到鸿鹄后&#xff0c;如何进行字段抽取&#xff0c;以及图表的展示。 字段抽取&#xff1a;由原来采用视图的方式&#xff0…

Rider无法识别Todo Comment

最近因为vs code很难识别到代码中的usage和definition&#xff0c;改用Rider了。 但是一开始就哪里有点不对&#xff0c; 比如我主题的颜色总是有些地方无法识别出来。比如我每次从Unity中点击脚本文件&#xff0c;都只能识别到某一个特定的文件夹&#xff0c;而不能打开整个…

机器人技术及其影响

目录 1.概念 2.发展 3.应用领域 4.对人类的益处 1.概念 机器人是指能够自主执行任务的机械设备或电子设备。它们通常具有一定的感知、决策和执行能力&#xff0c;能够接收和处理来自外部环境的信息&#xff0c;并做出相应的行动。 机器人的形态和功能各异&#xff0c;可以是…

Python接口测试- requests 发送 post 请求的几种方法

前言&#xff1a; POST 请求用于向服务器发送数据。与 get 相比更安全&#xff0c;同时 post 请求一般会带来数据的更改。 GET 请求不论我们怎么构造&#xff0c;最终都是通过 URL 向服务器传递数据&#xff0c;而 post 通过消息体&#xff08;报文主体&#xff09;发送请求。…

简单的职员管理系统 SpringBoot企业员工信息java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 简单的职员管理系统 SpringBoot 系统有1权限&#xf…

海外电子商务源代码跨境系统开发,Java现成代码全开源

海外电子商务跨境系统的开发是一个复杂的过程&#xff0c;而利用现成的Java代码进行开发可以节省时间和成本。下面是海外电子商务跨境系统开发的全开源步骤。 第一步&#xff1a;需求分析和规划 在开发海外电子商务跨境系统之前&#xff0c;需要进行需求分析和规划。这包括确定…

迅镭激光PL12050重载型激光切管机中标国内知名企业美的集团!

近日&#xff0c;迅镭激光重型激光切管机中标国内知名企业——美的集团! 成立于2002年的菱王电梯&#xff0c;是美的集团暖通与楼宇事业部旗下的专业电梯品牌 &#xff0c;业务覆盖电(扶)梯的研发、设计、制造、销售、安装和维保&#xff0c;自主研发的8m/s超高速电梯和8吨超重…

使用雅克比矩阵计算Rossler映射的lyapunov exponent图谱

Rossler映射如下: 雅可比行列式方法 计算Henon映射的Lyapunov exponent图谱,算法描述为: 0:初始化:初始化用到的值。参数a:[0,1.4],b:0.3,初始值x和y:1,迭代次数M:2000。 1:遍历参数a:计算不同a值所对应的Henon映射的Lyapunov exponent图谱。 2:迭代M次:…

selenium爬虫与配置谷歌浏览器的driver问题

用selenium爬虫时&#xff0c;明明已经安装了selenium模块&#xff0c;程序却运行不了。在使用selenium之前必须先配置浏览器对应版本的webdriver 本文主要涉及驱动有问题driver 网上有很多手动的方法&#xff08;查看谷歌浏览的版本然后在其他博主分享的webdriver中下载与自己…

MySQL存储结构及索引

文章目录 MySQL结构1.2存储引擎介绍1.3存储引擎特点InnoDB逻辑存储结构 MyISAMMemory区别及特点存储引擎选择 索引索引概述索引结构BTreeHash索引分类聚集索引&二级索引索引语法SQL性能分析索引优化最左前缀法则范围查询字符串不加引号模糊查询or连接条件数据分布影响覆盖索…

13个Python最佳编程技巧,越早知道越好

每天我们都会面临许多需要高级编码的编程挑战。你不能用简单的 Python 基本语法来解决这些问题。在本文中&#xff0c;我将分享 13 个高级 Python 脚本&#xff0c;它们可以成为你项目中的便捷工具。如果你目前还用不到这些脚本&#xff0c;你可以先添加收藏&#xff0c;以备留…

js迭代器与生成器

目录 迭代器next可迭代对象自定义类的迭代迭代器的中断 生成器生成器函数返回值与传递参数生成器的提前结束生成器的语法糖使用生成器实现自定义类迭代 async和awaitawait 迭代器 迭代器&#xff08;iterator&#xff09;&#xff0c;可以把它当做是一个接口&#xff0c;用户可…

Vue3 Props组件简单应用(子组件获取父组件数据)

去官网学习→Props | Vue.js 运行示例&#xff1a; 代码&#xff1a;App.vue <template><img alt"Vue logo" src"./assets/logo.png"><!-- 传递数据 key value--><Mycomponent :dataTest"content" :dataNmub&…

GPT-3.5 人工智能还是人工智障?——西红柿炒钢丝球!!

人工智能还是人工智障&#xff1f;——西红柿炒钢丝球 西红柿炒钢丝球的 基本信息西红柿炒钢丝球的 详细制作方法材料步骤 备注幕后花絮。。。。。。。。。关于GPT-3.5&#xff0c;你的看法&#xff1a; 西红柿炒钢丝球的 基本信息 西红柿炒钢丝球是一道具有悠久历史的传统中式…

leetcode经典算法——快速幂

实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。 暴力方法肯定是循环循环n次&#xff0c; 每一次*x 显然此方法遇到大的数字会超时 那么我们要引进一个思想&#xff0c;快速幂算法 例如&#xff1a; x^97 我们可以看出&a…

柜柜软件报价单滑动闪屏解决办法

柜柜下载地址:家具设计软件免费下载-家居设计软件手机版下载-柜柜App官网 出现的问题现象: 原因:笔记本使用的集成显卡,切换到独立显卡即可解决 异常修复.

ONVIF对讲功能漫谈

ONVIF对讲功能漫谈 前言一、onvif对讲功能和onvif协议关系大吗?二、如何上报设备支持onvif对讲功能呢?三、onvif协议中哪个接口上报音频解码配置?四、献上抓包报文:前言 本篇文章尝试使用提问的方式来分享onvif对讲功能那点事。 一、onvif对讲功能和onvif协议关系大吗? on…

windows10中配置mmhuman3d

分类&#xff1a;动作捕捉 github地址&#xff1a;https://github.com/open-mmlab/mmhuman3d 所需环境&#xff1a;Windows10&#xff0c;CUDA11.6&#xff0c;conda 4.13.0&#xff0c;Visual Studio 2017 目录 一.新建Pytorch基本环境1.创建并激活环境2.安装ffmpeg3.安装 PyT…

21、stm32使用LTDC驱动LCD

注&#xff1a;本文基于stm32使用FMC驱动SDRAM(IS42S32800G-6BLI)工程继续开发 本例使用安富莱的H743XIH板子驱动LTDC点亮7寸LCD 硬件接线&#xff1a;RGB888 一、cubemx配置 1、LTDC配置 注意此引脚应于上面的硬件接线图一致 2、配置DMA2D 3、背光引脚和触摸引脚 4、时钟…