桶排序和基数排序 Java
桶式排序
概念
有限个数字m,每个数字的大小都在1与n之间,则我们可以假设有n个桶,遍历m个数字,将其存入对应的桶中(如数字的值为3,就存入3号桶,桶的值对应存入数字的个数)
例子
有数字3,3,5,1,2,大小均在0-5之间,所以我们假设有5个桶,分别标号1,2,3,4,5,遍历所有数字,将其存入桶中,则存储之后,所有桶的计数如下:
桶号 | 1 | 2 | 3 | 4 | 5 |
计数 | 1 | 1 | 2 | 0 | 1 |
桶的倒出顺序 | 数字队列 |
5号桶倒出1个5 | 5 |
4号桶倒出0个4 | 5 |
3号桶倒出2个3 | 5,3,3 |
2号桶倒出1个2 | 5,3,3,2 |
1号桶倒出1个1 | 5,3,3,2,1 |
如上所示,我们成功将所给数列按照从大到小的排序,反之,如果从1号桶开始倒出,我们会得到从小到大排列的数字
代码实现(JAVA)
![](/assets/blank.gif)
//桶式排序 public class BucketSort{public static void main(String[] args){int[] a = {2,4,15,11,6,3,7,19,8,5,4};sort(a,19);}//桶式排序函数//a是要排序的数组//max是最大数字(这里我们默认数字最小为0)public static void sort(int[] a,int max){//声明一个数组,这就是桶,编号从0到max的桶,一共max+1个int[] count = new int[max + 1];//遍历数组,用桶计数for(int i = 0;i < a.length;i++){count[a[i]]++;}//将桶里面的数字倒出for(int i = max;i > 0;i--){while(count[i] > 0){System.out.print(i + " ");count[i]--;}}} }
![](/assets/blank.gif)
弊端
如果我们的数字波动范围非常大,比如1到10000,那么我们需要一个10000元素数组的空间开销,而且在倒出数字的时候需要遍历10000个桶,这样效率是非常低的,于是我们有了基于桶式排序的基数排序
基数排序
概念
基于桶式排序,将要排序的数字一位一位的比较,经历多次桶式排序,得出最终的序列
如果要排序的元素可以分成多位,并且每一位都在一个固定的范围内,则可以用这种排序方法,如对10进制数字的排序
例子
有数字23,35,9,73,3,314,11,1234,5,可以看出来,每一位数字的取值范围都是0到9,所以我们可以用10个桶来进行排序,分别编号0到9。
- 第一遍排序,按照最低位数字将各个数字存入桶中:
桶号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 11 | 23,73,3 | 314,1234 | 35,5 | 9 |
桶的倒出顺序 | 数字队列 |
9 | 9 |
8 | 9 |
7 | 9 |
6 | 9 |
5 | 9,35,5 |
4 | 9,35,5,314,1234 |
3 | 9,35,5,314,1234,23,73,3 |
2 | 9,35,5,314,1234,23,73,3 |
1 | 9,35,5,314,1234,23,73,3,11 |
0 | 9,35,5,314,1234,23,73,3,11 |
我们可以看到第一遍排序好的数字还是很乱的,可能还不能基数排序的妙处,不急,下面我们进行第二次排序
- 第二遍排序,将第一次排好的序列9,35,5,314,1234,23,73,3,11,按照第二位的数字存入桶中(只有一位的数第二位为0):
桶号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 9,5,3 | 314,11 | 23 | 35,1234 | 73 |
桶的倒出顺序 | 数字队列 |
9 | |
8 | |
7 | 73 |
6 | 73 |
5 | 73 |
4 | 73 |
3 | 73,35,1234 |
2 | 73,35,1234,23 |
1 | 73,35,1234,23,314,11 |
0 | 73,35,1234,23,314,11,9,5,3 |
我们发现,第二遍之后,有些数字好像已经排序好了,经过两次排序,或许你已经能看出来一些基数排序的原理了,下面我们进行第三遍排序
- 第三遍排序,将第二次排好的序列73,35,1234,23,314,11,9,5,3,按照第三位的数字存入桶中(只有两位的数第三位为0):
桶号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 73,35,23,11,9,5,3 | 1234 | 314 |
桶的倒出顺序 | 数字队列 |
9 | |
8 | |
7 | |
6 | |
5 | |
4 | |
3 | 314 |
2 | 314,1234 |
1 | 314,1234 |
0 | 314,1234,73,35,23,11,9,5,3 |
第三遍排序结束,相信你已经看出来基数排序的原理了,如果你还不懂,后面会有一个flash,清晰明了的一步一步为你分解基数排序,在这之前,让我们先勤勤恳恳的把第四遍,也是最后一遍排序完成
- 第四遍排序,将第三次排好的序列314,1234,73,35,23,11,9,5,3,按照第四位的数字存入桶中(只有三位的数第四位为0):
桶号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 314,73,35,23,11,9,5,3 | 1234 |
桶的倒出顺序 | 数字队列 |
9 | |
8 | |
7 | |
6 | |
5 | |
4 | |
3 | |
2 | |
1 | 1234 |
0 | 1234,314,73,35,23,11,9,5,3 |
代码实现(JAVA)
正常情况下,我们是要告诉我们的排序方法,我们最高位的数字是几位的,这样在最高位也排序完成后就会停止排序,但是我们在这段代码中用了一个叫hasNum的boolean型变量,用来表征我们的数组中是否还存在更高的位数,具体实现参见下面的代码,有注释,不难理解(PS:虽然省事了,方法更通用了,但是也产生了额外的开销)
![](/assets/blank.gif)
public class RadixSort{public static void main(String[] args){//声明要排序的数组int[] data = {73,22,93,867494,43,55,123,8978,10000,14,28,65,39,81,33,100,567};//调用基数排序函数sort(data,10);//输出排序后的数组for(int i = 0;i < data.length;i++){System.out.print(data[i] + " ");}}///基数排序函数//a表示要排序的数组//d表示每一位数字的范围(这里是10进制数,有0~9一共10种情况)public static void sort(int[] a,int d){//n用来表示当前排序的是第几位int n = 1;//hasNum用来表示数组中是否有至少一个数字存在第n位boolean hasNum = false;//二维数组temp用来保存当前排序的数字//第一维d表示一共有d个桶//第二维a.length表示每个桶最多可能存放a.length个数字int[][] temp = new int[d][a.length];int[] order = new int[d];while(true){//判断是否所有元素均无比更高位,因为第一遍一定要先排序一次,所以有n!=1的判断if(n != 1 && !hasNum){break;}hasNum = false;//遍历要排序的数组,将其存入temp数组中(按照第n位上的数字将数字放入桶中)for(int i = 0;i < a.length;i++){int x = a[i]/(n*10);if(x != 0){hasNum = true;}int lsd = (x%10);temp[lsd][order[lsd]] = a[i];order[lsd]++;}//k用来将排序好的temp数组存入data数组(将桶中的数字倒出)int k = 0;for(int i = 0;i < d;i++){if(order[i] != 0){for(int j = 0;j < order[i];j++){a[k] = temp[i][j];k++;} }order[i] = 0;}n++;}} }
![](/assets/blank.gif)
基数排序(给英文字符串排序)
排序规则
- 字符串更长的在前
- z在最前,a在最后
代码实现(JAVA)
总感觉代码写的比较笨,但是智商确实有点不够用了..............
![](/assets/blank.gif)
public class RadixSort_Letter{public static void main(String[] args){//声明要排序的数组String[] a = {"ac","ee","ef","b","z","f","ep","gaaa","azh","az","r"};//调用基数排序函数sort(a,4);//输出排序后的数组for(int i = a.length - 1;i >= 0;i--){System.out.print(a[i] + " ");}}///基数排序函数//a是要排序的数组//m表示数组元素最高位数,如我们排序的数组中位数最高的元素为gaaa,有4位public static void sort(String[] a,int m){int n = 0;//27表示每一位字符分成27类,其中1~26对应'a'~'z'//第0位专门用来存放没有高位字符的数组元素,如在比较第二位字符时,b,z,f等没有第二位字符的元素就存在temp[0]中//相对应的,ac存在temp[1]中,ef存在temp[5]中String[][] temp = new String[27][a.length];int[] order = new int[27];while(n < m){//这里声明String类型的数组b,将数组a中的每个元素倒序,然后放入数组b//如a[0]="abc",则b[0]="cba"//之所以这样做,是为了解决下面调用charAt方法时索引的问题,脑子太笨,没想到更好的方法String[] b = new String[a.length];for(int i = 0;i < a.length;i++){if(a[i].length() > 1){StringBuffer sb = new StringBuffer(a[i]);sb.reverse();b[i] = new String(sb);}else{b[i] = a[i];}}for(int i = 0;i < a.length;i++){if(a[i].length() > n){int lsd = b[i].charAt(n) - 'a' + 1;temp[lsd][order[lsd]] = a[i];order[lsd]++;}else{temp[0][order[0]] = a[i];order[0]++;}}int k = 0;for(int i = 0;i < 27;i++){for(int j = 0;j < order[i];j++){a[k] = temp[i][j];k++;}order[i] = 0;}n++;}} }
![](/assets/blank.gif)
桶排序和基数排序 Java相关推荐
- 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序
冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...
- 计数排序、桶排序和基数排序
计数排序 当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k).计数排序不是比较排序,排序的速度快于任何比较排序算法. 由于用来计数的数组C的长度取决于待排序数组中数据的 ...
- 三种线性排序算法 计数排序、桶排序与基数排序-BYVoid
转自:BYVoid [非基于比较的排序] 在计算机科学中,排序是一门基础的算法技术,许多算法都要以此作为基础,不同的排序算法有着不同的时间开销和空间开销.排序算法有非常多种,如我们最常用的快速排序和堆 ...
- 三种线性排序算法 计数排序、桶排序与基数排序—— 转自:BYVoid
三种线性排序算法 计数排序.桶排序与基数排序 [非基于比较的排序] 在计算机科学中,排序是一门基础的算法技术,许多算法都要以此作为基础,不同的排序算法有着不同的时间开销和空间开销.排序算法有非常多种, ...
- 十大经典排序算法(图解与代码)——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序(Python and Java)
排序 重新排列表中的元素,使表中的元素按照关键字递增或者递减 内部排序: 指在排序期间,元素全部存放在内存中的排序 外部排序: 指在排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求不断 ...
- 左神桶排序和基数排序
桶排序 计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中.作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数.计数排序不是比较排序,所以他优于任何比较排序. ...
- 计数排序、桶排序和基数排序的运算性能对比及总结区别(附python代码)
首先证明一波排序算法的运算性能,如下图.对于50万个数据的无序列表,时间复杂度为的桶排序和计数排序明显比复杂度为的归并排序和快速排序性能好至少一个数量级. 1. 计数排序 1.1 基本原理:首先确定 ...
- 【完整可运行源码+GIF动画演示】十大经典排序算法系列——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序
以前也零零碎碎发过一些排序算法,但总是不系统, 这次彻底的对排序系列做了一个整体的规划, 小伙伴们快快mark哦~ [GIF动画+完整可运行源代码]C++实现 冒泡排序--十大经典排序算法之一 [GI ...
- 【数据结构笔记38】桶排序、基数排序、多关键字排序、排序算法汇总比较
本次笔记内容: 10.3.1 桶排序 10.3.2 基数排序 10.3.3 多关键字排序 10.4 排序算法比较 文章目录 排序算法背景 桶排序 基数排序 多关键字排序(基数排序) 排序算法的比较 排 ...
最新文章
- mysql星火_mysql的执行计划
- android 活动外的类,Android – 活动外的startActivityForResult?
- VTK:相互作用之MouseEventsObserver
- 美赛开赛在即,你准备好了吗?
- linux修改组的选项名字为,Linux用户、组及权限管理浅析
- Spark提交 指定 kerberos 认证信息
- 9 FI配置-财务会计-维护会计年度变式
- git 将dev分支的代码合并到master并添加对应的Tag
- 解决python使用happybase连接hbase报错thriftpy2.transport.base.TTransportException....TSocket read 0 bytes
- 12000.PAC19XX电源监测芯片
- easy~算法刷题第三天
- 衡量文章词汇复杂度Type Token Ratio (TTR)
- Chrome插件之一键保存网页为PDF1.1发布
- 汇编:call和jmp
- 用matplotlib画sigmoid函数
- 图像的仿射变换原理、Homography、alpha通道以及python实现
- vue开发之图片加载不出来问题解决
- 阿卡迪亚大学计算机专业好考吗,申请阿卡迪亚大学究竟难不难?
- python word保存图_Python 将本地图片存储到 Word 文档
- 操作系统采用可变分区分配存储管理方法期末复习题