基数排序适合于有不同位数的大小数字,例如以下数列:
核心思想是:
先找十个桶:0~9
第一轮按照元素的个位数排序
桶内分别存放上述数组元素的个位数,按照数组元素的顺序依次存放
之后,按照从左向右,从上到下的顺序依次取出元素,组成新的数组。
在新的数组中,进行第二轮,按照十位数排序,依次存放于桶中:
按照之前的顺序取出,组成新的数组。
进行第三轮,按照百位数排序:
将百位数的元素取出之后,我们发现新的数组已经变成了有序数组
大家也已经发现,排序进行的轮数就是最大数的位数,这几轮进行之后,也就完成了基数排序。
全流程为此图:
进入代码阶段:
代码阶段一:实现第一轮个位数的排序
注意以下几点:
1.1.计算最大数的位数,可以通过此方法,加空字符转字符串使用length
int maxLength =(max+"").length();
1.2.得使用二维数组存储元素在桶中的位置:一个是余数位,一个是在在桶中第几个位置
1.3打印测试二维数组的方法为:
//打印二维数组,测试
for(int[] nums:temp){
System.out.println(Arrays.toString(nums));
测试第一轮是否正确的全部代码
package demo4;
import java.util.Arrays;
/**
* 基数排序
*
* 2019年2月14日
*/
public class RadixSort {
public static void main(String[] args) {
int[] arr = new int[]{23,6,9,287,56,1,789,34,65,653};
//System.out.println(Arrays.toString(arr));
radixSort(arr);
//System.out.println(Arrays.toString(arr));
}
public static void radixSort(int[] arr){
//存数组中最大的数字,为了知道循环几次
int max = Integer.MIN_VALUE;//(整数中的最小数)
//遍历数组,找出最大值
for(int i=0;i<arr.length;i++){
if(max<arr[i]){
max=arr[i];
}
}
//计算最大数是几位数,,此方法计较绝妙
int maxLength =(max+"").length();
//用于临时存储数据的数组
int[][] temp = new int[10][arr.length];
//用于存储桶内的元素位置
int[] counts = new int[arr.length];
//第一轮个位数较易得到余数,第二轮就得先除以十再去取余,之后百位除以一百
//可以看出,还有一个变量随循环次数变化,为了取余
//循环的次数
for(int i=0,n=1;i<maxLength;i++,n*=10){
//每一轮取余
for(int j=0;j<arr.length;j++){
//计算余数
int ys= (arr[j]/n)%10;
//把便利店数据放在指定数组中,有两个信息,放在第几个桶+数据应该放在第几位
temp[ys][counts[ys]] = arr[j];
//记录数量
counts[ys]++;
}
if(i==0){
//打印二维数组,测试
for(int[] nums:temp){
System.out.println(Arrays.toString(nums));
}
}
}
}
}
结果如下,验证第一轮通过
代码阶段二:实现第一轮取余存储之后,我们需要重新按照顺序(从左向右,从上向下)把元素从桶中拿出来组成一个新的数组,下一轮迭代时使用此新的数组
部分参考代码如下:
//记录取的数字应该放到位置
int index=0;
//每一轮循环之后把数字取出来
for(int k=0;k<counts.length;k++){
//记录数量的数组中当前余数记录不为零
if(counts[k]!=0){
for(int l=0;l<counts[k];l++){
//取出元素
arr[index]= temp[k][l];
index++;
}
//取出后把数量置为零
counts[k]=0;
}
}
至此,基数排序也写完了,运行结果及代码如下:
全部代码:`在这里插入代码片
package demo4;
import java.util.Arrays;
/**
* 基数排序
*
* 2019年2月14日
*/
public class RadixSort {
public static void main(String[] args) {
int[] arr = new int[] { 23, 6, 9, 287, 56, 1, 789, 34, 65, 653 };
System.out.println(Arrays.toString(arr));
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void radixSort(int[] arr) {
// 存数组中最大的数字,为了知道循环几次
int max = Integer.MIN_VALUE;// (整数中的最小数)
// 遍历数组,找出最大值
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
// 计算最大数是几位数,,此方法计较绝妙
int maxLength = (max + "").length();
// 用于临时存储数据的数组
int[][] temp = new int[10][arr.length];
// 用于存储桶内的元素位置
int[] counts = new int[arr.length];
// 第一轮个位数较易得到余数,第二轮就得先除以十再去取余,之后百位除以一百
// 可以看出,还有一个变量随循环次数变化,为了取余
// 循环的次数
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
// 每一轮取余
for (int j = 0; j < arr.length; j++) {
// 计算余数
int ys = (arr[j] / n) % 10;
// 把便利店数据放在指定数组中,有两个信息,放在第几个桶+数据应该放在第几位
temp[ys][counts[ys]] = arr[j];
// 记录数量
counts[ys]++;
}
// 记录取的数字应该放到位置
int index = 0;
// 每一轮循环之后把数字取出来
for (int k = 0; k < counts.length; k++) {
// 记录数量的数组中当前余数记录不为零
if (counts[k] != 0) {
for (int l = 0; l < counts[k]; l++) {
// 取出元素
arr[index] = temp[k][l];
index++;
}
// 取出后把数量置为零
counts[k] = 0;
}
}
}
}
}