0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基数排序知识点全面概括

lhl545545 来源:电子发烧友网 2018-02-05 14:30 次阅读

数据背景

在基数排序中,我们不能再只用一位数的序列来列举示例了。一位数的序列对基数排序来说就是一个计数排序。

这里我们列举无序序列 T = [ 2314, 5428, 373, 2222, 17 ]

排序原理

上面说到基数排序不需要进行元素的比较与交换。如果你有一些算法的功底,或者丰富的项目经验,我想你可能已经想到了这可能类似于一些“打表”或是哈希的做法。而计数排序则是打表或是哈希思想最简单的实现。

计数排序

计数排序的核心思想是,构建一个足够大的数组 hashArray[],数组大小需要保证能够把所有元素都包含在这个数组上 。

假设我们有无序序列 T = [ 2314, 5428, 373, 2222, 17 ]

首先初始化数组 hashArray[] 为一个全零数组。当然,在 Java 里,这一步就不需要了,因为默认就是零了。

在对序列 T 进行排序时,只要依次读取序列 T 中的元素,并修改数组 hashArray[] 中把元素值对应位置上的值即可。这一句有一些绕口。打个比方,我们要把 T[0] 映射到 hashArray[] 中,就是 hashArray[T[0]] = 1. 也就是 hashArray[2314] = 1. 如果序列 T 中有两个相同元素,那么在 hashArray 的相应位置上的值就是 2。

下图是计数排序的原理图:

(假设有无序序列:[ 5, 8, 9, 1, 4, 2, 9, 3, 7, 1, 8, 6, 2, 3, 4, 0, 8 ])

基数排序知识点全面概括

基数排序原理图

上面的计数排序只是一个引导,好让你可以循序渐进地了解基数排序。

基数排序知识点全面概括

上面这幅图,或许你已经在其他的博客里见到过。这是一个很好的引导跟说明。在基数排序里,我们需要一个很大的二维数组,二维数组的大小是 (10 * n)。10 代表的是我们每个元素的每一位都有 10 种可能,也就是 10 进制数。在上图中,我们是以每个数的个位来代表这个数,于是,5428 就被填充到了第 8 个桶中了。下次再进行填充的时候,就是以十位进行填充,比如 5428 在此时,就会选择以 2 来代表它。

基数排序知识点全面概括

算法优化

在算法的原理中,我们是以一张二维数组的表来存储这些无序的元素。使用二维数组有一个很明显的不足就是二维数组太过稀疏。数组的利用率为 10%。

在寻求优化的路上,我们想到一种可以压缩空间的方法,且时间复杂度并没有偏离得太厉害。那就是设计了两个辅助数组,一个是 count[],一个是 bucket[]。count 用于记录在某个桶中的最后一个元素的下标,然后再把原数组中的元素计算一下它应该属于哪个“桶”,并修改相应位置的 count 值。直到最大数的最高位也被添加到桶中,或者说,当所有的元素都被被在第 0 个桶中,基数排序就结束了。

优化后的原理图如下:

基数排序知识点全面概括

算法实现

import org.algorithm.array.sort.interf.Sortable;

/**

*

* 基数排序/桶排序

*

*

* @author Q-WHai

* @see http://blog.csdn.net/lemon_tree12138

* @version 0.1.1

*/

public class RadixSort implements Sortable {

@Override

public int[] sort(int[] array) {

if (array == null) {

return null;

}

int maxLength = maxLength(array);

return sortCore(array, 0, maxLength);

}

private int[] sortCore(int[] array, int digit, int maxLength) {

if (digit >= maxLength) {

return array;

}

final int radix = 10; // 基数

int arrayLength = array.length;

int[] count = new int[radix];

int[] bucket = new int[arrayLength];

// 统计将数组中的数字分配到桶中后,各个桶中的数字个数

for (int i = 0; i < arrayLength; i++) {

count[getDigit(array[i], digit)]++;

}

// 将各个桶中的数字个数,转化成各个桶中最后一个数字的下标索引

for (int i = 1; i < radix; i++) {

count[i] = count[i] + count[i - 1];

}

// 将原数组中的数字分配给辅助数组 bucket

for (int i = arrayLength - 1; i >= 0; i--) {

int number = array[i];

int d = getDigit(number, digit);

bucket[count[d] - 1] = number;

count[d]--;

}

return sortCore(bucket, digit + 1, maxLength);

}

/*

* 一个数组中最大数字的位数

*

* @param array

* @return

*/

private int maxLength(int[] array) {

int maxLength = 0;

int arrayLength = array.length;

for (int i = 0; i < arrayLength; i++) {

int currentLength = length(array[i]);

if (maxLength < currentLength) {

maxLength = currentLength;

}

}

return maxLength;

}

/*

* 计算一个数字共有多少位

*

* @param number

* @return

*/

private int length(int number) {

return String.valueOf(number).length();

}

/*

* 获取 x 这个数的 d 位数上的数字

* 比如获取 123 的 0 位数,结果返回 3

*

* @param x

* @param d

* @return

*/

private int getDigit(int x, int d) {

int a[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };

return ((x / a[d]) % 10);

}

}

基数排序过程图

如果我们的无序是 T = [ 2314, 5428, 373, 2222, 17 ],那么其排序的过程就如下两幅所示。

基数排序过程图-1

基数排序知识点全面概括

基数排序过程图-2

基数排序知识点全面概括

复杂度分析

基数排序知识点全面概括

其中,d 为位数,r 为基数,n 为原数组个数。

在基数排序中,因为没有比较操作,所以在复杂上,最好的情况与最坏的情况在时间上是一致的,均为 O(d * (n + r))。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
收藏 人收藏

    评论

    相关推荐

    FPGA排序-冒泡排序介绍

    排序算法是图像处理中经常使用一种算法,常见的排序算法有插入排序、希尔排序、选择排序、冒泡排序、归
    发表于 07-17 10:12 609次阅读
    FPGA<b class='flag-5'>排序</b>-冒泡<b class='flag-5'>排序</b>介绍

    运放知识点

    `运放知识点`
    发表于 08-20 20:58

    【信盈达】C语言知识点的总结

    一、嵌入式C/单片机C/标准C知识点知识点1:嵌入式C、标准C、单片机C区别知识点2:程序组成和程序原则知识点3:变量类型(函数、数组、指针、结构体等类型)知识点4:常用的运算符和关系
    发表于 10-08 14:41

    使用PADS软件进行PCB设计,有哪些基础知识点

    使用PADS软件进行PCB设计,有哪些基础知识点?发现知识点很多、很杂、很乱,有没有聚合归纳统一的内容给到
    发表于 08-20 12:07

    电机与电气控制基础的知识点

    电机就是我们平时俗称的“马达”,电机是依据电磁感应定律实现电能转换或传递的一种电磁装置。电机的主要作用是产生驱动转矩,作为用电器或各种机械的动力源。而电机与电气控制技术的一些基础的知识点是不论是在学习还是工作中都是需要牢记的。今天分享的就是关于电机与电气控制基础的一些基本的知识点
    发表于 01-22 06:54

    电机与拖动知识点及其试题

    电机与拖动知识点分析一、基本知识与基础知识知识点常考题目二、直流电机一、基本知识与基础知识
    发表于 06-29 07:10

    资料下载:基数排序:*** 与 MSD

    1.算法原理基数排序是通过“分配”和“收集”过程来实现排序。1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)2)收集,再将放置在0~9号桶中的数据
    发表于 07-05 07:57

    算法的原理是什么?基数排序是如何实现的?

    算法的原理是什么?基数排序是如何实现的?有哪几种方法可以实现基数排序
    发表于 07-05 07:42

    STM32外部中断知识点概述

    STM32外部中断概述知识点(1)知识点(2)知识点(3)中断服务函数外部中断常用库函数外部中断的一般配置步骤知识点(1)STM32的每个IO都可以作为外部中断输入。STM32的中断控
    发表于 08-16 07:43

    关于AUTOSAR架构的知识点看完你就懂了

    关于AUTOSAR架构的知识点看完你就懂了
    发表于 10-18 07:41

    各种排序算法的时间空间复杂度、稳定性

    各种排序算法的时间空间复杂度、稳定性一、排序算法分类:二、排序算法比较:注:1、归并排序可以通过手摇算法将空间复杂度降到O(1),但是时间复杂度会提高。2、
    发表于 12-21 07:48

    基数排序是怎么排的_基数排序详细过程

    基数排序详细过程如下文所述。基数排序最初是用在打孔卡片制表机上的一种排序算法,基数排序从最低为开始来排序的,从低位到高位,按位
    的头像 发表于 02-05 14:11 1.7w次阅读
    <b class='flag-5'>基数排序</b>是怎么排的_<b class='flag-5'>基数排序</b>详细过程

    基数排序 java代码实现

    本文详细概括基数排序以及java代码实现。基数排序又称桶排序,相对于常见的比较排序基数排序
    发表于 02-05 14:46 891次阅读
    <b class='flag-5'>基数排序</b> java代码实现

    C语言实现简单的基数排序

    本文主要阐述的类容是C语言实现简单的基数排序基数排序是一种分配排序,其基本思想是:排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序
    发表于 02-05 14:57 1677次阅读
    C语言实现简单的<b class='flag-5'>基数排序</b>

    常用的非比较排序算法:计数排序基数排序,桶排序的详细资料概述

    这篇文章中我们来探讨一下常用的非比较排序算法:计数排序基数排序,桶排序。在一定条件下,它们的时间复杂度可以达到O(n)。
    的头像 发表于 06-18 15:11 6792次阅读
    常用的非比较<b class='flag-5'>排序</b>算法:计数<b class='flag-5'>排序</b>,<b class='flag-5'>基数排序</b>,桶<b class='flag-5'>排序</b>的详细资料概述