思路分析
代码如下:
package com.shujujiegou;
import sun.awt.im.SimpleInputMethodWindow;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Hello {
public static void main(String[] args) {
int arr[]=new int[]{53,3,542,748,14,214};
int temp[]=new int[arr.length]; //归并排序需要一个格外的空间
System.out.println("排序前的数组是:"+Arrays.toString(arr));
System.out.println("***************");
jishu(arr);
System.out.println("***************");
System.out.println("排序后的数组是:"+Arrays.toString(arr));
}
public static void jishu(int []arr){
//1.得到数组中最大的数的位数
int max=arr[0];
for (int i = 0; i <arr.length ; i++) {
if(arr[i]>max){
max=arr[i];
}
}
//得到最大数是几位数
int maxLength=(max+ "").length();
//定义一个二维数组,表示10个桶,每个桶就是一个一维数组
//二维数组包含十个一维数组,为了防止在放入数的时候,数据溢出,则每一个一维数组(桶),大小定位arr.length
//基数排序是使用空间换时间的经典算法
int [][] bucket=new int[10][arr.length];
//为了记录每个桶中,实际存放了多少数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
//bucketElementCounts[0],记录的就是bucket[0]桶放入的数据个数
int[] bucketElementCounts=new int[10];
for (int q = 0,n=1; q <maxLength ; q++,n*=10) {
//针对每个元素的对应位进行排序处理 第一次是个位 第二次是十位 第三次是百位
for (int i = 0; i <arr.length ; i++) {
//取出每个元素对应位的值
int gewei=arr[i]/n%10;
//放入到对应的桶中
bucket[gewei][bucketElementCounts[gewei]]=arr[i];
bucketElementCounts[gewei]++;
}
//按照这个桶的位置(一维数组的下标依次取出数据,放入原来的数组)
int index=0;
//遍历每一个桶,并将桶中数据放入原来的数组
for (int i = 0; i <bucketElementCounts.length ; i++) {
//如果桶中有数据。我们才放入到原数组中
if(bucketElementCounts[i]!=0){
for (int j = 0; j <bucketElementCounts[i] ; j++) {
arr[index++]=bucket[i][j];
}
}
//第q+1轮处理后,需要将每个bucketElementCounts[k]=0
bucketElementCounts[i]=0;
}
System.out.println(Arrays.toString(arr));
}
}
}
代码运行效果如下:
总结:
- 基数排序在数据规模较小的时候,和快速排序、归并排序速度相差无异,但是在数据规模特别大(千万级及以上)的时候,排序效率特别特别高。
- 基数排序是非常典型的空间换时间的排序算法,如果在排序的时候,数据规模n特别大的情况下,运行程序可能会报error,这是由于java内存不足导致。