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,注意的问题

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

相关文章
|
5月前
|
Java
基数排序(java)
基数排序(java)
|
搜索推荐 算法 Java
【算法】基数排序的原理与Java实现
基数排序(Radix Sort)是一种非比较性的排序算法,它根据元素的位数逐位进行排序。基数排序的核心思想是将待排序的元素按照低位到高位的顺序进行排序,每一位都使用稳定的排序算法(通常是计数排序或桶排序)。通过多次按位排序,最终可以得到有序的结果
112 0
|
搜索推荐 Java
深入了解基数排序:原理、性能分析与 Java 实现
基数排序(Radix Sort)是一种非比较性排序算法,它根据元素的每个位上的值来进行排序。基数排序适用于整数或字符串等数据类型的排序。
162 2
深入了解基数排序:原理、性能分析与 Java 实现
|
Java
Java实现基数排序
Java实现基数排序
118 0
Java实现基数排序
|
算法 搜索推荐 Java
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】
|
存储 人工智能 算法
八大排序算法Java实现(下)-快排、归排、基数排序
八大排序算法Java实现(下)-快排、归排、基数排序
162 0
八大排序算法Java实现(下)-快排、归排、基数排序
|
8天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
17天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
4天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
22 9
|
7天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####