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

本篇只是讨论桶排序的具体实现,想了解更多算法内容可以在我的博客里搜,建议大家看看这篇排序算法总结:排序算法总结_鱼跃鹰飞的博客-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*100queues[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();}}}}//把排完序的数组复制到原来的数组,如果这个方法是有返回值的,也可以直接返回copyfor(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.hqwc.cn/news/63860.html

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

相关文章

[git] git基础知识

git是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目 git易于学习&#xff0c;性能极快 什么是版本控制&#xff1f; 版本控制是一种记录文件内容变化&#xff0c;以便将来查阅特定版本修订情况&#xff0c;可以记录文件修改历史…

【ElasticSearch入门】

目录 1.ElasticSearch的简介 2.用数据库实现搜素的功能 3.ES的核心概念 3.1 NRT(Near Realtime)近实时 3.2 cluster集群&#xff0c;ES是一个分布式的系统 3.3 Node节点&#xff0c;就是集群中的一台服务器 3.4 index 索引&#xff08;索引库&#xff09; 3.5 type类型 3.6 doc…

通达OA SQL注入漏洞【CVE-2023-4166】

通达OA SQL注入漏洞【CVE-2023-4166】 一、产品简介二、漏洞概述三、影响范围四、复现环境POC小龙POC检测工具: 五、修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损…

我的Python教程:使用Pyecharts画柱状图

Pyecharts是一个用于生成 Echarts 图表的 Python 库。Echarts 是一个基于 JavaScript 的数据可视化库&#xff0c;提供了丰富的图表类型和交互功能。通过 Pyecharts&#xff0c;你可以使用 Python 代码生成各种类型的 Echarts 图表&#xff0c;例如折线图、柱状图、饼图、散点图…

电脑开不了机如何解锁BitLocker硬盘锁

事情从这里说起&#xff0c;不想看直接跳过 早上闲着无聊&#xff0c;闲着没事干&#xff0c;将win11的用户名称改成了含有中文字符的用户名&#xff0c;然后恐怖的事情发生了&#xff0c;蓝屏了… 然后就是蓝屏收集错误信息&#xff0c;重启&#xff0c;蓝屏收集错误信息&…

Windows下安装 Redis

目录 1.下载 1.1.Redis官网 1.2.github下载地址 2.安装步骤 2.1.解压Redis压缩包 2.2.创建临时服务 2.3.启动客户端 2.4.注册Redis服务 3.总结 4.致谢 1.下载 1.1.Redis官网 Download | Redis Redis 官方网站没有提供 Windows 版的安装包&#xff0c;但可以通过…

x11 gtk qt gnome kde 之间的区别和联系

Linux 下的图形库介绍 一、Linux 图形领域的基础设施 1.1 X Window X Window从逻辑上分为三层&#xff1a;X Server、X Client和X协议。 最底层的X Server&#xff08;X服务器&#xff09;主要处理输入/输出信息并维护相关资源&#xff0c;它接受来自键盘、鼠标的操作并将…

【ES】笔记-函数参数默认值

函数参数默认值 ES6 允许给函数参数赋值初始值 1. 形参初始值 具有默认值的参数&#xff0c;一般放到最后 function add(a,b,c10){return abc}let resultadd(1,2);console.log(result);2. 与解构赋值结合 function connect({host"127.0.0.1",username,password,port…

AI绘画网站都有哪些比较好用?

人工智能绘画网站是一种利用人工智能技术进行图像处理和创作的网站。这些绘画网站通常可以帮助艺术家以人工智能绘画的形式快速生成有趣、美丽和独特的绘画作品。无论你是专业的艺术家还是对人工智能绘画感兴趣的普通人&#xff0c;人工智能绘画网站都可以为你提供新的创作灵感…

【C语言】进阶指针,超详解,含丰富代码示例

文章目录 前言指针进阶的重点内容1.字符指针2.数组指针3.指针数组4.函数指针5.函数指针数组6. 指向函数指针数组的指针 总结 这里是初阶的链接&#xff0c;方便大家对照查看&#xff01;&#xff01;&#xff01;添加链接描述 前言 大家好呀&#xff0c;今天和大家将指针进阶…

运维监控学习笔记1

1、监控对象&#xff1a; 1、监控对象的理解&#xff1b;CPU是怎么工作的&#xff1b; 2、监控对象的指标&#xff1a;CPU使用率&#xff1b;上下文切换&#xff1b; 3、确定性能基准线&#xff1a;CPU负载多少才算高&#xff1b; 2、监控范围&#xff1a; 1、硬件监控&#x…

JVM内存区域

预备 为了更好的理解类加载和垃圾回收&#xff0c;先要了解一下JVM的内存区域&#xff08;如果没有特殊说明&#xff0c;都是针对的是 HotSpot 虚拟机。&#xff09;。 Java 源代码文件经过编译器编译后生成字节码文件&#xff0c;然后交给 JVM 的类加载器&#xff0c;加载完…