小白初识 - 基数排序(RadixSort)
基数排序算是桶排序和计数排序的衍生吧,因为基数排序里面会用到这两种其中一种。
基数排序针对的待排序元素是要有高低位之分的,比如单词adobe,activiti,activiti就高于adobe,这个是根据ascll码来的。
现在我们可以提出一个问题,怎样对字典里面的单词进行排序呢?
比如我们现在有如下单词:
"Java", "Mongodb", "Redis", "Kafka", "javascript", "mysql", "mybatis", "kindle",
"rpc", "Algorithm", "mergeSort", "quickSort", "Adobe"
我们要怎么对它排序呢,这里就可以用到基数排序了,基数排序的原理就是我们将一个元素按高低位分成单个个体,比如Adobe我们
就分成A,d,o,b,e,Algorithm我们就分成A,l,g,o,r,i,t,h,m,然后我们从右往左,依次比较即可。
但是这里Adobe和Algorithm并不能直接比较,因为他们的长短不一,所以在比较之前我们应该找到最长的元素的长度,然后将其余短的元素补全
到一样长:
Adobe0000
Algorithm
这样才可以形成比较,从右往左,0:m,0:h,0:t,0:i,e:r,b:o,o:g,d:l,A:A,我们就可以比较出来Adobe > Algorihtm
跟着以下的图片会更清楚原理:

从上图我们可以看出,基数排序会从右往左依次比较(即在我们的程序实现里面需要遍历很多次),而具体要遍历多少次则取决于最长的元素有多长,从右往左对每个位
的元素比较可以用到桶排序或计数排序,桶排序和计数排序的时间复杂度都是O(n),假设最大的元素长度为K,则基数排序的时间复杂度为O(k * n),而k一般不会有多大,
可以视为常量,所以基数排序的时间复杂度也是O(n)。 以下是我的Java实现:
package com.structure.sort; /**
* @author zhangxingrui
* @create 2019-01-30 14:58
**/
public class RadixSort { public static void main(String[] args) {
/*int[] numbers = {19, 36, 24, 10, 9, 29, 1, 0, 3, 60, 100, 1001, 999, 520, 123, 96};
radixSort(numbers);
for (int number : numbers) {
System.out.println(number);
}*/ String[] words = {"Java", "Mongodb", "Redis", "Kafka", "javascript", "mysql", "mybatis", "kindle", "rpc", "Algorithm", "mergeSort", "quickSort", "Adobe"};
// String[] words = {"Java", "mongodb", "Kafka"};
radixSort(words);
for (String word : words) {
System.out.println(word.replaceAll("0", ""));
}
} /**
* @Author: xingrui
* @Description: 基数排序(单词)
* @Date: 15:53 2019/1/30
*/
private static void radixSort(String[] words){
int exp = 0;
int maxLength = getMaxLength(words);
autoComplete(words, maxLength);
for(exp = 1; exp <= maxLength; exp++){
countingSort(words, exp);
}
} /**
* @Author: xingrui
* @Description: 计数排序(单词)
* @Date: 13:57 2019/1/30
*/
private static void countingSort(String[] words, int exp){
int n = words.length;
String[] r = new String[n];
int[] c = new int[122]; for(int i = 0; i < n; ++i){
int asc = (byte)words[i].charAt(words[i].length() - exp);
c[asc]++;
} for(int i = 1; i < 122; ++i){
c[i] = c[i-1] + c[i];
} for (int i = n - 1; i >= 0; --i){
int asc = (byte)words[i].charAt(words[i].length() - exp);
int index = c[asc];
r[index - 1] = words[i];
c[asc]--;
} for(int i = 0; i < n; ++i){
words[i] = r[i];
}
} /**
* @Author: xingrui
* @Description: 基数排序(纯数字)
* @Date: 15:00 2019/1/30
*/
private static void radixSort(int[] numbers){
int exp = 0;
int maxNumber = getMaxNumber(numbers);
for(exp = 1; maxNumber/exp > 0; exp *= 10){
countingSort(numbers, exp);
}
} /**
* @Author: xingrui
* @Description: 计数排序(纯数字)
* @Date: 13:57 2019/1/30
*/
private static void countingSort(int[] numbers, int exp){
int n = numbers.length; int[] r = new int[n];
int[] c = new int[10]; for(int i = 0; i < n; ++i){
c[numbers[i]/exp % 10]++;
} for(int i = 1; i < 10; ++i){
c[i] = c[i-1] + c[i];
} for (int i = n - 1; i >= 0; --i){
int index = c[numbers[i] / exp % 10];
r[index - 1] = numbers[i];
c[numbers[i] / exp % 10]--;
} for(int i = 0; i < n; ++i){
numbers[i] = r[i];
}
} /**
* @Author: xingrui
* @Description: 自动补全单词
* @Date: 16:38 2019/1/30
*/
private static void autoComplete(String[] words, int maxLength){
int i = 0;
for (String word : words) {
if(word.length() < maxLength){
int value = maxLength - word.length();
StringBuilder sb = new StringBuilder();
for(int j = 0; j < value; ++j){
sb.append("0");
}
words[i] = word + sb;
}
i++;
}
} /**
* @Author: xingrui
* @Description: 获取字符串最大的长度
* @Date: 15:56 2019/1/30
*/
private static int getMaxLength(String[] words){
int maxLength = words[0].length();
for(int i = 1; i < words.length; ++i){
if(words[i].length() > maxLength)
maxLength = words[i].length();
}
return maxLength;
} /**
* @Author: xingrui
* @Description: 获取最大的数字
* @Date: 15:56 2019/1/30
*/
private static int getMaxNumber(int[] numbers){
int maxNumber = numbers[0];
for(int i = 1; i < numbers.length; ++i){
if(numbers[i] > maxNumber)
maxNumber = numbers[i];
}
return maxNumber;
} }
其中需要注意就是在排序之前需要找到最大的元素长度以确定循环次数和根据最大元素长度补全比较短的元素。
程序执行结果:

需要特别说明的是,文中的图片均截图极客网王争老师的专栏《数据结构与算法之美》,如有侵权,请联系我删除。
有需要的朋友也可以去订阅这个专栏,讲的挺不错的,没有视频,只有文字和音频。

小白初识 - 基数排序(RadixSort)的更多相关文章
- 基数排序(RadixSort)
1 基数排序的特点是研究多个关键字key,且多个key之间有权重之分, 或者可把单个key建模为含有多个key的排序 而计数排序.桶排序始终只有个一个key,或者说围绕着一个比较规则 Ex:比较 ...
- 小白初识 - 计数排序(CountingSort)
计数排序,属于桶排序特殊的一种. 当要排序n个数据的时候,如果所处的范围不大,我们可以取其中的最大值K,并将数据分散在K个桶里面, 每个桶里面的数据都是相同的(这样省去了桶内排序的时间),然后顺序取出 ...
- 小白初识 - 快速排序(QuickSort)
我个人觉得快速排序和归并排序有相似之处,都是用到了分治的思想,将大问题拆分成若干个小问题. 不同的地方是归并排序是先把大问题拆分好了之后再排序,而快速排序则是一边拆分,一边排序. 快速排序的原理就是, ...
- 小白初识 - 归并排序(MergeSort)
归并排序是一种典型的用分治的思想解决问题的排序方式. 它的原理就是:将一个数组从中间分成两半,对分开的两半再分成两半,直到最终分到最小的单位(即单个元素)的时候, 将已经分开的数据两两合并,并且在合并 ...
- 排序算法----基数排序(RadixSort(L))单链表智能版本
转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割 ...
- 排序算法----基数排序(RadixSort(L,max))单链表版本
转载http://blog.csdn.net/Shayabean_/article/details/44885917博客 先说说基数排序的思想: 基数排序是非比较型的排序算法,其原理是将整数按位数切割 ...
- 模板化的七种排序算法,适用于T* vector<T>以及list<T>
最近在写一些数据结构以及算法相关的代码,比如常用排序算法以及具有启发能力的智能算法.为了能够让写下的代码下次还能够被复用,直接将代码编写成类模板成员函数的方式,之所以没有将这种方式改成更方便的函数模板 ...
- 6种基础排序算法java源码+图文解析[面试宝典]
一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...
- 20172328 2018-2019《Java软件结构与数据结构》第五周学习总结
20172328 2018-2019<Java软件结构与数据结构>第五周学习总结 概述 Generalization 本周学习了第九章:排序与查找,主要包括线性查找和二分查找算法和几种排序 ...
随机推荐
- 【题解】洛谷P1373 小a和uim之大逃离(坐标DP)
次元传送门:洛谷P1373 思路 设f[i][j][t][1/0]表示走到(i,j)时 小a减去uim的差值为t 当前是小a取(0) uim取(1) 那么转移就很明显了 f[i][j][t][]=(f ...
- 修改jupyter notebook的默认路径
我的系统环境是win10,安装了anaconda3 for python 3.6.6首先需要配置notebook的变量环境:打开 cmd 输入命令 jupyter notebook --generat ...
- Git IDEA Move or commit them before merge
提交代码遇到这个问题. Move or commit them before merge 百度了一下都是在Gitbash 中敲命令. 在团队协作中 你总不能去敲命令吧 后来在组长的怂恿下,我删除了一个 ...
- js 时间转换毫秒的四种方法(转)
将时间转换为毫秒数的方法有四个: Date.parse()Date.UTCvalueOf()getTime() 1. Date.parse():该方法接受一个表示日期的字符串参数,然后尝试根据这个日期 ...
- Ubuntu18.04挂载exfat格式移动硬盘
1.安装exfat-fuse 命令:sudo apt-get install exfat-fuse 2.重新插拔移动硬盘,即可识别 查看挂载命令:lsblk
- Java面试题整理2
多线程部分 并行和并发的区别? 并行指两个或多个事件同一时刻发生:并发指两个或多个事件同一时间间隔发生. 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件. 线程和进程的区别? 进程是程序运 ...
- 使用echart的雷达图的时候,如果文字越界的解决办法记录,标签文字自动换行
使用echart的雷达图的时候,如果文字越界的解决办法记录,标签文字自动换行 前几天项目中有一个图表的是用echart生成的,遇到一个问题,就是在手机端显示的售时候,如果文字太长就会超出div,之前的 ...
- $.trim() 去除空格方法 (验证使用)
- Java使用多线程实现Socket多客户端的通信
要想详细了解socket,大家请自行百度,我这里只简单介绍. 在网络中,我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程.而socket编程就是为了完成两个唯一进程之间的通信(一个是客户端, ...
- Linuxg环境搭建
1.使用VMWARE软件安装虚拟机,创建打开将进入桌面. 2.配置静态IP.IP环境关系到能否使用网络进行软件的下载,即apt的使用. 1).找到文件并作如下修改:sudo vim /etc/netw ...