首页 > 编程语言 >基本算法-基数排序

基本算法-基数排序

时间:2023-04-21 20:12:00浏览次数:37  
标签:基本 arr int 算法 基数排序 数组 802 排序

思想

当我们需要对一组数据进行排序时,常规的排序算法(如快速排序、归并排序等)通常是比较排序,即通过比较元素之间的大小关系来进行排序。但有时候我们需要对一组数据按照它们的“数字位”进行排序,此时比较排序并不是最优的选择,这时候基数排序就显得非常有效了。

基数排序是一种非比较排序算法,它根据元素的每个“数字位”(比如个位、十位、百位等)来对元素进行排序,其基本思想是将整数按照位数切割成不同的数字,然后按照每个位数分别比较。具体来说,基数排序可以分为以下几个步骤:

  1. 将数组中的元素按照个位数进行排序:从个位数开始,对于每个数字,将其放到对应的桶中;
  2. 将桶中的元素按照顺序依次取出来,组成新的数组;
  3. 将新数组中的元素按照十位数进行排序:从十位数开始,对于每个数字,将其放到对应的桶中;
  4. 将桶中的元素按照顺序依次取出来,组成新的数组;
  5. 依次按照百位数、千位数......对元素进行排序,直到所有位数均已考虑。

基数排序的时间复杂度为O(d(n+k)),其中d表示位数,k表示每一位可能的取值范围,n表示元素的数量。显然,基数排序的效率与每一位的取值范围k有关,当k较小而d较大时,基数排序的效率会很高。

代码

public class RadixSort {

    public static void radixSort(int[] arr) {
    
        // 先找到最大的数
        int max = Integer.MIN_VALUE;
        for (int num : arr) {
            max = Math.max(num, max);
        }
        // 最大数的位数
        int maxDigit = 0;
        while (max != 0) {
            ++maxDigit;
            max = max / 10;
        }
        // 10进制
        int base = 10;
        // 新建桶, 0-9是10个数所以有10个桶
        int[][] buckets = new int[base][arr.length];

        // 有多少位就进行多少轮的排序
        for (int i = 0; i < maxDigit; i++) {
            int[] bucketsCount = new int[base];
            for (int num : arr) {
                // 获取位数上的值,这里要是不会写也可以用字符串
                int digit = (int) (num / Math.pow(base, i)) % 10;
                // 把它加到桶里
                buckets[digit][bucketsCount[digit]] = num;
                // 这一位的数的数量++,即记录每个桶中元素的数量,为了之后还能把它放回原数组
                bucketsCount[digit]++;
            }
            int index = 0;
            // 有几个桶循环几次
            for (int j = 0; j < bucketsCount.length; ++j) {
                // 一个桶里有多少个数
                int count = bucketsCount[j];
                // 如果桶里有数
                if (count != 0) {
                    // 取出放回原数组,这里其实已经排序了,因为桶本身是有序的
                    for (int k = 0; k < count; ++k) {
                        arr[index++] = buckets[j][k];
                    }
                }
            }
        }
    }

    public static void main(String... args) {
        int[] arr = { 170, 45, 75, 90, 802, 24, 2, 66 };
        RadixSort.radixSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

过程举例

假设有一个整数数组 arr = [170, 45, 75, 90, 802, 24, 2, 66],要求使用基数排序将其从小到大排序。

首先,我们需要确定最大数的位数。最大数是802,所以它的位数是3。因此,我们需要进行3轮排序。

第一轮排序按个位数排序。遍历整个数组,把每个数按个位数的值分到0-9的桶中。比如170、90、802在个位数上分别是0、0、2,它们分别被放入编号为0、2的桶中。排序后的数组为[170, 90, 802, 2, 24, 45, 75, 66]。

第二轮排序按十位数排序。遍历排序后的数组,把每个数按十位数的值分到0-9的桶中。比如802、45、75在十位数上分别是0、4、7,它们分别被放入编号为0、4、7的桶中。排序后的数组为[2, 24, 45, 66, 75, 170, 802, 90]。

第三轮排序按百位数排序。遍历排序后的数组,把每个数按百位数的值分到0-9的桶中。比如2、45、66在百位数上分别是0、4、6,它们分别被放入编号为0、4、6的桶中。排序后的数组为[2, 24, 45, 66, 75, 90, 170, 802]。

最终得到的就是一个有序数组了。

标签:基本,arr,int,算法,基数排序,数组,802,排序
From: https://www.cnblogs.com/maoqifansBlog/p/17341636.html

相关文章

  • Markdown基本用法学习
    **@author:Noiimplant@data:2023-4-20*/一、Markdown的基本介绍1.1markdown背景markdown是一种轻量级标记语言,她与徐人们使用易读易写的纯文本格式编写文档。Markdown语言在2004由约翰·格鲁伯(英语:JohnGruber)创建。Markdown编写的文档可以导出HTML、Word、图像......
  • Django框架——静态文件配置、form表单、request对象、连接数据库、ORM简介、ORM基本
    配置文件介绍SECRET_KEY='0yge9t5m9&%=of**qk2m9z^7-gp2db)g!*5dzb136ys0#)*%*a'#盐DEBUG=True#调试模式,等项目上线的时候,改成False#配置数据库DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3',#默认是自......
  • 基于RL(Q-Learning)的迷宫寻路算法
    强化学习是一种机器学习方法,旨在通过智能体在与环境交互的过程中不断优化其行动策略来实现特定目标。与其他机器学习方法不同,强化学习涉及到智能体对环境的观测、选择行动并接收奖励或惩罚。因此,强化学习适用于那些需要自主决策的复杂问题,比如游戏、机器人控制、自动驾驶等。强化......
  • Redis 为何使用Nearly LRU 算法淘汰数据
    Redis使用该LRU算法淘汰过期数据吗?不是的。由于LRU算法需要用链表管理所有的数据,会造成大量额外的空间消耗。大量的节点被访问就会带来频繁的链表节点移动操作,从而降低了Redis性能。Redis的内存空间是很宝贵的,而维护LRU的双向链表需要使用比较多的额外空间,至少需要一......
  • JVM垃圾回收机制之对象回收算法
    在前面的文章中,介绍了JVM内存模型分为:堆区、虚拟机栈、方法区、本地方法区和程序计数器,其中堆区是JVM中最大的一块内存区域,在Java中的所有对象实例都保存在此区域,它能被所有线程共享。在Java中还有一个重要的机制:GC(垃圾收集器),堆是GC管理的主要区域,本文会带大家了解GC机制。GC......
  • 开心档之C++ 基本语法
    C++基本语法C++程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。对象- 对象具有状态和行为。例如:一只狗的状态-颜色、名称、品种,行为-摇动、叫唤、吃。对象是类的实例。类- 类可以定义为描述对......
  • Python用哈希算法查找相似图片(包括不同分辨率,不同大小,不同格式的图片)
    #-*-coding:utf-8-*-'''Python用哈希算法查找相似图片并放入[_df]的文件夹中相似图片包括不同分辨率,不同大小,不同格式,只要图片相似就会算重复文件安装cv2pipinstallopencv-python'''importosimportcv2importnumpyasnpimportshutilimportrandomclas......
  • 从原理聊JVM(一):染色标记和垃圾回收算法
    作者:京东科技 康志兴1JVM运行时内存划分1.1运行时数据区域•方法区属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。运行时常量池,属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用。JDK1.8之前,Hotspot虚拟机对......
  • Diffie-Hellman密钥交换算法
    目录前置知识密钥交换算法隐私计算常用到各种加密算法,那么双方如何协商得到同一个不被泄露的密钥呢?一种做法是基于RSA,拥有公钥的一方将随机私钥加密提供给对方,对方再利用私钥解密出密钥。于是双方都得到了会话密钥。上面这种基于非对称加密的方法是SSL最古老的密钥协商方式,早......
  • C++11之std::future对象的基本用法
    1、//futureexample#include<iostream>//std::cout#include<future>//std::async,std::future#include<chrono>//std::chrono::milliseconds//anon-optimizedwayofcheckingforprimenumbers:boolis_prime......