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

本篇只是讨论桶排序的具体实现,想了解更多算法内容可以在我的博客里搜,建议大家看看这篇排序算法总结:排序算法总结_鱼跃鹰飞的博客-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] + " ");
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文带你快速掌握如何在Windows系统和Linux系统中安装部署MongoDB

文章目录 前言一、 Windows系统中的安装启动1. 下载安装包2. 解压安装启动3. Shell连接(mongo命令)4. Compass-图形化界面客户端 二、 Linux系统中的安装启动和连接1. 下载安装包2. 解压安装3. 新建并修改配置文件4. 启动MongoDB服务5. 关闭MongoDB服务 总结 前言 为了巩固所学…

全面解析接口测试和接口测试必需掌握的知识要点

接口测试 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 接口测试原理 通过测试程序模拟客…

牛客小白月赛71E题题解

文章目录 猫猫与数学问题建模问题分析1.转换条件2.分析新的gcd3.方法1筛约数判断代码 4.方法2筛质因子判断代码 猫猫与数学 问题建模 给定两个正整数a&#xff0c;b&#xff0c;问能否找到最小的整数c&#xff0c;使得gcd(ac,bc)不等于1&#xff0c;若可以输出c&#xff0c;不…

牛奶产业链的工业“链主品牌”利乐是如何诞生的?

瑞典的利乐公司&#xff0c;一个在乳品产业链中占据重要地位的“链主品牌”&#xff0c;通过提供创新的包装材料和解决方案&#xff0c;在全球范围内占据了显著的市场份额。利乐从不生产一滴奶&#xff0c;却赚取了中国乳业 75%的利润&#xff0c;一年创收超过 800 亿人民币。在…

提取有像素的掩码和原图

有些数据集给的掩码是全黑图片&#xff0c;需要将全黑的掩码剔除&#xff0c;保留有标签的掩码。 DDR-dataset 眼底图像处理 from PIL import Image import cv2 import osdef extract_mask_and_original(mask_path, original_path, output_folder):# 读取黑白掩码图片和同名原…

Spring 使用注解储存对象

文章目录 前言存储 Bean 对象五大注解五大注解示例配置包扫描路径读取bean的示例 方法注解 Bean Bean 命名规则重命名 Bean 前言 通过在 spring-config 中添加bean的注册内容&#xff0c;我们已经可以实现基本的Spring读取和存储对象的操作了&#xff0c;但在操作中我们发现读…

【果树农药喷洒机器人】Part3:变量喷药系统工作原理介绍

本专栏介绍&#xff1a;免费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、变量喷药系统工作原理二、液压通路设计与控制系统封装2.1液压通路…

活动预告|聊聊Moonbeam治理和生态Grants

为Web3设计良好的治理机制是一项具有挑战性的任务。去中心化治理系统对于Web3的发展至关重要。高效运行的治理机制有助于项目的稳定运行&#xff0c;同时又能提升社区用户的参与度&#xff0c;Web3开发者的凝聚力和活跃度&#xff0c;甚至促进更多创新的商业应用在公链生态落地…

VLAN监控及常见问题排查

局域网&#xff0c;我们通常称为LAN&#xff0c;是一种由基于同一地理位置的设备组成的网络&#xff0c;可实现它们之间的通信&#xff0c;局域网的虚拟对应物是虚拟局域网或 VLAN。VLAN 增强了 LAN&#xff0c;提供了进行更改的灵活性、更高的可扩展性和更好的安全性。 使用 …

【Spring专题】Spring底层核心原理解析

目录 前言阅读导航前置知识Q1&#xff1a;你能描述一下JVM对象创建过程吗&#xff1f;Q2&#xff1a;Spring的特性是什么&#xff1f;前置知识总结 课程内容一、Spring容器的启动二、一般流程推测2.1 扫描2.2 IOC2.3 AOP 2.4 小结三、【扫描】过程简单推测四、【IOC】过程简单推…

install imap error

【错误翻译】 Try to run this command from the system terminal. Make sure that you use the correct version of pip installed for your Python interpreter located at D:\Program Files (x86)\Python\Python39\python.exe. 尝试从系统终端运行此命令。请确保使用安装在…

竞赛项目 疫情数据分析与3D可视化 - python 大数据

文章目录 0 前言1 课题背景2 实现效果3 设计原理4 部分代码5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据全国疫情数据分析与3D可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff0…

Vue+SpringBoot项目开发:后台登陆功能的实现(二)

写在开始:一个搬砖程序员的随缘记录文章目录 一、SpringBoot项目的搭建二、数据库配置1、新建数据库2、新建用户表 三、SpringBoot项目的配置 一、SpringBoot项目的搭建 项目搭建传送门&#xff1a;从零开始&#xff0c;SpringBoot项目快速搭建 二、数据库配置 1、新建数据库…

nacos安装与启动相关问题(启动闪退和显示此站点的连接不安全)

问题&#xff1a;启动闪退 尝试&#xff1a; 使用记事本打开cmd文件&#xff0c;在文件结尾处新增两行 pause endlocal 如果还有问题&#xff1a;ERROR Nacos failed to start, please see D:\dev\nacos\logs\nacos.log for more details 尝试&#xff1a; 在nacos的bin目…

【100天精通python】Day30:使用python操作数据库_数据库基础入门

专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12375510.html 1 数据库基础知识介绍 1.1 什么是数据库&#xff1f; 数据库是一个结构化存储和组织数据的集合&#xff0c;它可以被有效地访问、管理和更新。数据库的目的是为了提供一种可靠的…

Python-OpenCV中的图像处理-边缘检测

Python-OpenCV中的图像处理-边缘检测 边缘检测Canny算子 边缘检测Canny算子 Canny 边缘检测是一种非常流行的边缘检测算法&#xff0c;是 John F.Canny 在 1986 年提出的。它是一个有很多步构成的算法&#xff1a;噪声去除、计算图像梯度、非极大值抑制、滞后阀值等。 Canny(i…

Android:换肤框架Android-Skin-Support

gihub地址&#xff1a;https://github.com/ximsfei/Android-skin-support 样例&#xff1a; 默认&#xff1a; 更换后&#xff1a; 一、引入依赖&#xff1a; // -- 换肤依赖implementation skin.support:skin-support:4.0.5// skin-supportimplementation skin.support:ski…

Linux系统的Centos7扩容主分区

前言&#xff1a;在学习C#的过程中电脑里面的项目&#xff0c;镜像越来越多之前装系统的时候分配的空间太小导致Linux系统空间不足&#xff0c;应该怎么办呢&#xff0c;lets go 跟着我来将centOS 7扩容吧. 1.关闭虚拟机&#xff0c;在VMWare的”此虚拟机设置“中找到硬盘&…

半年报增幅超预期,但汤臣倍健还是喂不饱年轻人?

文|琥珀消研社 作者|朱古力 谁也想不到&#xff0c;进入三伏天以后首个运动潮流会是“晒背”。 小红书上近5万条“晒背”相关的笔记里&#xff0c;多数都是对“什么时候晒背”、“晒多久合适”等入门级问题的答疑解惑&#xff0c;微博热搜词条更是针对性地给出了“晒背最佳时…

19 | 首尔自行车共享需求预测

文章目录 首尔自行车共享需求预测1. 问题陈述2. 数据描述3. 项目的业务用途是什么?4. 模型构建步骤5. 数据可视化1)热力图2)按季节分的租赁自行车数量3)假日和非假日租赁自行车数量4)太阳辐射与租赁自行车数量5)租赁自行车数量和一天的小时数6)特征重要性首尔自行车共享…