基数排序详解(Radix sort)

简介: 基数排序详解(Radix sort)

一、简单释义

1、算法概念

冒泡排序(Radix sort)是属于“分配式排序”(distribution sort),又称“桶排序”(bucket sort),顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

2、算法目的

 将原本乱序的数组变成有序,可以是 LSD或者 MSD  (文中以LSD为例)

3、算法思想

 将整数按位数切割成不同的数字,然后按每个位数分别比较。基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

4、算法由来

 这个算法的名字由来是因为每个数按照它的位数进行拆分,对每一个对应的位数进行比较排序,直到所有位数都进行过一遍排序位置

二、核心思想

「迭代」:类似的事情,不停地做。

「哈希」:将一个数字映射到一个数组中。

「队列」:采用先进先出的数据结构。

三、图形展示

1、宏观展示

ebebe72d478047629168a76aa2eb2612.png

2、微观展示

 以324、61、4、10、222、166、512这个数组为例

9e2262baf13c43278ad2dd4dd6a9d599.png

 1、第一次排序:按照每个元素个位数的值填入到对应的桶中,324的个位数是4所以放到4号桶中。从桶向外取值形成新的数组是以队列的先进先出的方式进行的。

cdd2d91b1972407992bb7d8a8f67592d.png

 2、第二次排序:按照每个元素十位数的值填入到对应的桶中,十位上没有数的元素默认填入到0号桶中即可。其余操作和第一次排序是一样的。比如512十位数的值是1,那么把512这个元素放到1号桶中。从1号桶中取值的时候先取10这个元素,在取512这个元素。

a9cf9e84f6cf4ecfa3912a1502af52fb.png

 3、第三次排序:按照每个元素百位数的值填入到对应的桶中,百位上没有数的元素默认填入到0号桶中即可。其余操作和上面两次排序是一样的。数组中元素的最高位数就是基数排序要进行的排序的次数。

四、算法实现

1、实现思路

 将图形化展示的过程转换成对应的开发语言,本文中主要以Java语言为例来进行算法的实现。

 1. 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零;

 2. 从最低位开始,依次进行一次排序;

 3. 这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列;

 4. 重复步骤1~3,直到排序完成。

 能把整个过程描述清楚实现起来才会更加容易!!!

2、代码实现

import java.util.Arrays;
/**
 * @BelongsProject: demo
 * @BelongsPackage: com.wzl.Algorithm.RadixSort
 * @Author: Wuzilong
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-05-06 11:24
 * @Version: 1.0
 */
public class RadixSort {
    public static void main(String[] args) {
        int[] numArray={324,61,4,10,222,166,512};
        radixSort(numArray);
    }
    public static void radixSort(int[] arr) {
        // 获取数组中最大的数,确定最高位数
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        int maxLength = String.valueOf(max).length();
        // 定义一个桶,存储每个位数上的数字
        int[][] bucket = new int[10][arr.length];
        // 定义一个数组,记录每个桶中存储的数据个数
        int[] bucketCount = new int[10];
        // 按照从低位到高位的顺序进行排序
        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
            // 将每个数的第 i+1 位数存到桶中
            for (int j = 0; j < arr.length; j++) {
                int digit = arr[j] / n % 10;
                bucket[digit][bucketCount[digit]++] = arr[j];
            }
            // 将桶中的数字重新放回到原数组中,这里要注意桶的顺序
            int index = 0;
            for (int j = 0; j < bucket.length; j++) {
                if (bucketCount[j] != 0) {
                    for (int k = 0; k < bucketCount[j]; k++) {
                        arr[index++] = bucket[j][k];
                    }
                    bucketCount[j] = 0;
                }
            }
            // 打印每次排序的结果
            System.out.println("第"+(i+1)+"次"+Arrays.toString(arr));
        }
    }
}

3、运行结果

e58618e66fed48548b52768adcf1adaa.png

五、算法描述

1、问题描述

 给定一个 n 个元素的整型数组,数组下标从 0开始,采用基数排序,将数组按照 「LSD」排列。

2、算法过程

整个算法过程分为以下几步:

 1) n个记录的关键字进行排序,每个关键字看成是一个d元组:ki=(ki1, ki2,…, kid) 其中c0 <=kij <=cr-1 ( 1 <=i <=n, 1 <=j <=d )

 2) 排序时先按kid 的值,从小到大将记录分到r(称为基数)个盒子中,再依次收集;

 3)然后按kid-1的值再这样作。直至按ki1分配和收集序列为止,排序结束。

3、算法总结

 首先,准备 10 个队列,进行若干次迭代 。每次迭代 ,先清空队列,然后取每个待排序数的对应十进制位,通过 哈希 ,映射到它对应的队列 中,然后将所有数字按照队列顺序 塞回 原数组 完成一次 迭代 。

 可以认为类似 关键字排序 ,先对 第一关键字 进行排序,再对第二关键字 排序,以此类推,直到所有关键字都有序为止。

六、算法分析

1、时间复杂度

 基数排序的时间复杂度为O(d*(n+k)),其中d为最大数的位数,n为待排序的数据个数,k为桶的个数。在数据分布均匀的情况下,基数排序的效率很高,但如果数据分布极端不均匀,则可能导致效率下降,因此在实际使用中需要根据具体情况进行选择。

2、空间复杂度

 基数排序的空间复杂度取决于排序过程中用到的辅助存储空间。在基数排序中,需要开辟多个桶(一般为10个)以及一个数组来存储排序结果,因此空间复杂度为O(n+k),其中n为待排序数组的长度,k为桶的个数。

3、算法稳定性

 基数排序不会破坏相等元素的相对顺序,所以是稳定的。


相关文章
|
机器学习/深度学习 测试技术 Python
【激活函数】基础回顾:带你认识神经网络中常见的激活函数
【激活函数】基础回顾:带你认识神经网络中常见的激活函数
2046 0
【激活函数】基础回顾:带你认识神经网络中常见的激活函数
|
安全 搜索推荐 智能硬件
让你的智能生活更便捷
天猫精灵是阿里巴巴旗下的一款智能音箱,它可以通过语音控制来执行各种任务,如播放音乐、查询天气、设置提醒等。作为一款智能家居控制中心,天猫精灵已经越来越受到人们的欢迎。本文将为你介绍一些天猫精灵的使用技巧,帮助你更好地利用这个智能设备,让你的智能生活更加便捷。
2812 2
|
机器学习/深度学习 存储 算法
深度学习中的稀疏注意力
深度学习中的稀疏注意力
1504 0
|
4月前
|
机器学习/深度学习 存储 人工智能
阿里云服务器计算型热门深度对比:计算型c8i、c8y、c9i、c9a实例性能对比与选购指南
阿里云服务器计算型实例选购餐卡,本文重点解析了主流的第八代(c8i、c8y、c8ae)与第九代(c9i、c9a)实例。其中,c8y基于自研倚天710 ARM架构,性价比突出,适合容器与微服务;c8i搭载Intel至强处理器,支持AMX加速,兼顾AI推理与通用计算;c9i采用第九代至强6处理器,单核性能最强,适用于AI推理与高并发场景;c9a基于AMD最新EPYC Turin,在数据库与金融量化场景中优势明显。
阿里云服务器计算型热门深度对比:计算型c8i、c8y、c9i、c9a实例性能对比与选购指南
|
11月前
|
安全 Ubuntu 应用服务中间件
基于code-server的云端编程环境部署
本文档描述如何在 Ubuntu 主机上部署 code-server(即“网页版 VS Code”),并通过 autossh 将服务反向隧道到跳板机、使用 Nginx 反向代理域名访问、以及使用 certbot 配置 HTTPS。适合在多设备间共享同一开发环境、并解决个人主机动态公网 IP 的访问问题。
1969 5
|
12月前
|
机器学习/深度学习 存储 并行计算
大模型推理加速技术:FlashAttention原理与实现
本文深入解析大语言模型推理加速的核心技术——FlashAttention。通过分析传统注意力机制的计算瓶颈,详细阐述FlashAttention的IO感知算法设计、前向反向传播实现,以及其在GPU内存层次结构中的优化策略。文章包含完整的CUDA实现示例、性能基准测试和实际部署指南,为开发者提供高效注意力计算的全套解决方案。
1865 10
|
运维 Serverless 调度
破解 vLLM + DeepSeek 规模化部署的“不可能三角”
vLLM 是一种便捷的大型语言模型(LLM)推理服务,旨在简化个人和企业用户对复杂模型的使用。通过 vLLM,用户可以轻松发起推理请求,享受高效、稳定的 LLM 服务。针对大规模部署 vLLM 的挑战,如大模型参数量、高效推理能力和上下文理解等,阿里云函数计算(FC)提供了 GPU 预留实例闲置计费功能,优化了性能、成本和稳定性之间的平衡。此外,FC 支持简便的部署流程和多种应用集成方式,帮助企业快速上线并管理 vLLM 服务。总结来说,vLLM 结合 FC 的解决方案为企业提供了强大的技术支持和灵活的部署选项,满足不同业务需求。
1195 94
破解 vLLM + DeepSeek 规模化部署的“不可能三角”
|
NoSQL Java Redis
Spring Boot集成Redisson详细介绍
Redisson是一个用于Java的分布式和高可用的Java对象的框架,它基于Redis实现。在Spring Boot应用程序中集成Redisson可以帮助我们更轻松地实现分布式锁、分布式对象、分布式集合等功能。本文将介绍如何在Spring Boot项目中集成Redisson,并展示一些基本用法。
2748 2
Spring Boot集成Redisson详细介绍
|
搜索推荐 算法
桶排序算法
桶排序是一种高效的排序算法,基于分治思想,理想时间复杂度为O(n)。它通过将数据分到多个桶中,每个桶再单独排序,最后按序合并各桶元素,从而实现整体有序。
767 0
|
存储 算法 Android开发
【算法基础】拓扑排序及实战
在图论中,如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个**有向无环图(DAG,Directed Acyclic Graph)**
1719 0

热门文章

最新文章