小白初识 - 基数排序(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 本周学习了第九章:排序与查找,主要包括线性查找和二分查找算法和几种排序 ...
随机推荐
- Eclipse配置多个Tomcat服务器
我们在开发大型web项目时,经常需要在eclipse中同时启动多个tomcat服务器来开启多个服务.这里讲解一下如何在eclipse中配置多个tomcat服务器. 配置步骤 1. 在tomcat官网( ...
- [LuoguP1064][Noip2006]金明的预算方案
金明的预算方案(Link) 题目描述 现在有\(M\)个物品,每一个物品有一个钱数和重要度,并且有一个\(Q\),如果\(Q = 0\),那么该物件可以单独购买,当\(Q != 0\)时,表示若要购买 ...
- Oracle 12.2 设置LOCAL_TEMP_TABLESPACE
12.2 设置LOCAL_TEMP_TABLESPACE SQL> select username,DEFAULT_TABLESPACE,TEMPORARY_TABLESPACE,LOCAL_ ...
- C#设计模式 —— 单例模式
嗯,这是本人的第一篇随笔,就从最简单的单例模式开始,一步一步地记录自己的成长. 单例模式是最常见的设计模式之一,在项目代码中几乎随处可见.这个设计模式的目的就是为了保证实例只能存在一个.单例模式往下还 ...
- es6解构赋值的几个用法
1.解构赋值可以轻松获取对象或者数组中的数据 var jsonData = { data: "111", data2: ["test","test2& ...
- 【Linux】日志分析及管理
日志的作用 用于记录系统.程序运行中发生的各种事件 eg: [root@localhost ~]# yum install -y httpd [root@localhost ~]# tail ...
- Redis 之复制-初入江湖
一.前言 在分布式系统中,为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复合负载均衡等需求.Redis也是如此,它为我们提供了复制的功能,实现了相同数据的多个Redis副本.复制 ...
- 调试日志——基于stm32的智能声光报警器(三)
智能声光报警器基本功能调试完成. 1.通过拨码开关来设置LED闪烁的频率. 2.关门时喇叭不想,灯熄灭. 3.旁路模式时,灯处于闪烁状态,此时关门灯扔闪烁. 关于此次代码我觉得还是有可以优化的地方,电 ...
- TINY4412:移植uboot、内核和挂接网络文件系统
开发环境: 单板:TINY4412-1611 系统:Ubuntu 16.04 64位 编译工具链:arm-linux-gcc-4.3.2 uboot版本:uboot_tiny4412-20130729 ...
- vue中-webkit-box-orient:vertical打包放到线上不显示
解决方法: 1.找到build文件夹 下的webpack.prod.conf.js文件 2.注释new OptimizeCSSPlugin({ css ...