java实现基数排序

简介: java实现基数排序

基数排序,又称为桶排序的拓展

1,接下来看图理解实现的过程

定义10个桶,相当于定义了一个二维数组,每个桶相当于一个以为数组

以数组中的每个数据的各个位数上的值进行比较,即先各位,再1十位,再百位…一直下去

以int data[] = {53,3,542,748,14,214}为例

对以个数的大小进行划分,顺序的存入到不同的桶中

第一轮,先判断各位上的数,得到的的数据为{542,53,3,14,214,748}

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20201104161749629.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3poZW5naHVpc2hlbmdx,size_16,color_FFFFFF,t_70#pic_center


20201104163220608.png

在将桶中的数据放回给原数组中,并将桶中的数据置空

第二轮,对十位进行排序,如果位数不够,则在前面补0

得到的的数据为{3, 14, 214, 542, 748, 53}

第三轮,对百位进行排序,桶中的数据置空,得到的数据为{3, 14, 53, 214, 542, 748}

这样就可以发现顺序已经拍好了

2,代码实现

原生代码实现

package sanguigu.sort;
import java.util.Arrays;
/**
 * 基数排序
 * 桶排序的应用
 * @author zhenghuisheng
 */
public class Jishu {
    public static void main(String[] args) {
        int dd[] = {53,3,542,748,14,214};
        jishu(dd);
    }
    public static void jishu(int a[]){
        //定义一个二维数组,用于存储数据,相当于定义了10个桶,每个桶代表一个一维数组
        //10表示0到9,而a.length表示我们做最坏的打算,可能将所有的数据都存在1个桶中
        int data[][] = new int[10][a.length];
        //定义一个数组,用于保存数据的个数,整型数组的每个数据默认为0
        int digitElement[] = new int[10];
        //需要遍历的次数取决去数组中最大数据的位数,位数小的数据前面补0
        //第一次遍历,即个数遍历
        //开始遍历数组中的每个数据
        for (int i = 0; i < a.length; i++) {
            //取余
            int k =  a[i] % 10;
            //digitElement[i],代表10个桶中的数据的个数,说白了就是一个计数器,但是可以记录下标,方便使用
            data[k][digitElement[k]] = a[i];
            //经典桶排序
            digitElement[k] ++ ;
        }
        //在存放在桶的数据中,将数据放回原来的数组中,即数组a中
        int index = 0;
        for (int i = 0; i < digitElement.length; i++) {
            if(digitElement[i] != 0){
                //遍历桶中的个数,将桶中的数据去除
                for (int j = 0; j < digitElement[i]; j++) {
                    a[index] = data[i][j];
                    index ++;
                }
            }
            //将存数据个数的桶中的数据置空
            digitElement[i] = 0;
        }
        System.out.println(Arrays.toString(a));
        System.out.println("=========================第一次遍历===========================");
        for (int i = 0; i < a.length; i++) {
            //取余
            int k =  a[i]/10 % 10;
            //digitElement[i],代表10个桶中的数据的个数,说白了就是一个计数器,但是可以记录下标,方便使用
            data[k][digitElement[k]] = a[i];
            //经典桶排序
            digitElement[k] ++ ;
        }
        //在存放在桶的数据中,将数据放回原来的数组中,即数组a中
        int index1 = 0;
        for (int i = 0; i < digitElement.length; i++) {
            if(digitElement[i] != 0){
                //遍历桶中的个数,将桶中的数据去除
                for (int j = 0; j < digitElement[i]; j++) {
                    a[index1] = data[i][j];
                    index1 ++;
                }
            }
            //将存数据个数的桶中的数据置空
            digitElement[i] = 0;
        }
        System.out.println(Arrays.toString(a));
        System.out.println("=========================第二次遍历===========================");
        for (int i = 0; i < a.length; i++) {
            //取余
            int k =  a[i]/100;
            //digitElement[i],代表10个桶中的数据的个数,说白了就是一个计数器,但是可以记录下标,方便使用
            data[k][digitElement[k]] = a[i];
            //经典桶排序
            digitElement[k] ++ ;
        }
        //在存放在桶的数据中,将数据放回原来的数组中,即数组a中
        int index2 = 0;
        for (int i = 0; i < digitElement.length; i++) {
            if(digitElement[i] != 0){
                //遍历桶中的个数,将桶中的数据去除
                for (int j = 0; j < digitElement[i]; j++) {
                    a[index2] = data[i][j];
                    index2 ++;
                }
            }
            //将存数据个数的桶中的数据置空
            digitElement[i] = 0;
        }
        System.out.println(Arrays.toString(a));
        System.out.println("=========================第三次遍历===========================");
    }
}
优化后
package sanguigu.sort;
import java.util.Arrays;
/**
 * 基数排序
 * 桶排序的应用
 * @author zhenghuisheng
 */
public class Jishu {
    public static void main(String[] args) {
        int dd[] = {53,3,542,748,14,214};
        jishu(dd);
    }
    public static void jishu(int a[]){
        //定义一个二维数组,用于存储数据,相当于定义了10个桶,每个桶代表一个一维数组
        //10表示0到9,而a.length表示我们做最坏的打算,可能将所有的数据都存在1个桶中
        int data[][] = new int[10][a.length];
        //定义一个数组,用于保存数据的个数,整型数组的每个数据默认为0
        int digitElement[] = new int[10];
        //需要遍历的次数取决去数组中最大数据的位数,位数小的数据前面补0
        int max = a[1];
        for (int i = 0; i < a.length; i++) {
            if(max < a[i]){
                max = a[i];
            }
        }
        //获取最大值,通过最大值来确定需要遍历的次数
        System.out.println(max);
        int num = (max + "").length();
        for (int j = 0; j <num ; j++) {
            for (int i = 0; i < a.length; i++) {
                //取余
                int k =  a[i] /(int)Math.pow(10,j) % 10;
                //digitElement[i],代表10个桶中的数据的个数,说白了就是一个计数器,但是可以记录下标,方便使用
                data[k][digitElement[k]] = a[i];
                //经典桶排序
                digitElement[k] ++ ;
            }
            //在存放在桶的数据中,将数据放回原来的数组中,即数组a中
            int index = 0;
            for (int i = 0; i < digitElement.length; i++) {
                if(digitElement[i] != 0){
                    //遍历桶中的个数,将桶中的数据去除
                    for (int k = 0; k < digitElement[i]; k++) {
                        a[index] = data[i][k];
                        index ++;
                    }
                }
                //将存数据个数的桶中的数据置空
                digitElement[i] = 0;
            }
            System.out.println(Arrays.toString(a));
            System.out.println("=========================第" +j+1+"次遍历===========================");
        }
3,时间复复杂度为:
时间复杂度为O(d*n) 。其中,n是数组长度,d是最大位数
4,注意的问题

由于该算法是以空间换时间,从而提高算法的效率,因此需要注意数据的大小,如果数据过大,很容易造成堆溢出

相关文章
|
10月前
|
Java
基数排序(java)
基数排序(java)
|
搜索推荐 算法 Java
【算法】基数排序的原理与Java实现
基数排序(Radix Sort)是一种非比较性的排序算法,它根据元素的位数逐位进行排序。基数排序的核心思想是将待排序的元素按照低位到高位的顺序进行排序,每一位都使用稳定的排序算法(通常是计数排序或桶排序)。通过多次按位排序,最终可以得到有序的结果
135 0
|
搜索推荐 Java
深入了解基数排序:原理、性能分析与 Java 实现
基数排序(Radix Sort)是一种非比较性排序算法,它根据元素的每个位上的值来进行排序。基数排序适用于整数或字符串等数据类型的排序。
226 2
深入了解基数排序:原理、性能分析与 Java 实现
|
Java
Java实现基数排序
Java实现基数排序
162 0
Java实现基数排序
|
算法 搜索推荐 Java
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
|
存储 人工智能 算法
八大排序算法Java实现(下)-快排、归排、基数排序
八大排序算法Java实现(下)-快排、归排、基数排序
174 0
八大排序算法Java实现(下)-快排、归排、基数排序
|
2月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
175 60
【Java并发】【线程池】带你从0-1入门线程池
|
25天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
77 23
|
1月前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
101 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
2月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
150 14