基数排序
1、基本原理
定义十个桶,桶的下标分别为0,1,2,3,4,5,6,7,8,9.
下标代表个位,十位或百位······的数字
每次排序对一位进行排序,先对个位进行排序,然后依次对十位、百位·········
示意图如下
2、具体代码实现
2.1、先得到数组中的最大数从而获取位数。
maxLength为该数组最大数有几位,从而获取下面循环的轮数。
//首先确定最大数值,以及位数
int max=arr[0];
for (int i = 0; i <arr.length ; i++) {
if(arr[i]>max){
max=arr[i];
}
}
//maxLength为有几位
int maxLength=(max+"").length();
2.2、再定义桶
桶是什么,二维数组
int[][] bucket=new int[10][arr.length];
第一个维度10代表0~~9这10个桶。
第二个维度arr.length代表每个桶的容量,由于可能会出现整个数组一位全部相同的情况如【21,31,221,121,51,61,71,231】.此时在排个位的时候所有的数字会放在一个桶中。
二维数组的结构以及上述的情况如下
因此二维数组的两个维度分别为10,arr.length。即为int[][] bucket=new int[10][arr.length];
2.3、将数字放入桶中
再定义一个桶记录数组,用于记录每个桶中的数字的个数。int[] elementCounts=new int[10];
定义一个变量element表示一个数字个位十位百位······的数字。
如:21个位的element为1。elementCounts[element]表示某位为element的数的个数,也就是该桶中数字的个数。
先定义一个循环,控制轮数,每一轮排一个位。轮数由数组中最大的数的位数决定。
再在该循环中再定义一个循环,遍历数组,把分别将数放入相应的桶中。
具体代码如下:
int n=1;//n*10^n后用分别获取十位百位个位······数
//maxLength为位数
//h用于控制轮数,轮数由数组中最大的数的位数决定
for (int h = 0; h < maxLength; h++) {
//循环遍历数组
for (int i = 0; i < arr.length ; i++) {
//计算当前个位十位百位的数值,element为个位,十位·····的数值
int element=arr[i]/n%10;
//读一下桶记录器当中的数据,也就是该位中
int count=elementCounts[element];//数组默认值为0,故count第一次被赋值时为0,count用于记录该位为element的个数
bucket[element][count]=arr[i];//初始值为bucket[element][0]=arr[0],也就是将个位(其他位)为element的数组元素放入桶中
elementCounts[element]=elementCounts[element]+1;//elementCounts[element]最开始为0,加一用于统计某位为element的个数
}//上面的代码实现了将数放入桶中
n=n*10;
}
2.4、将数字从桶中倒出到原数组中从而完成排序
定义一个index表示原数组下标
然后尝试将bucket[][]中的数字放入原数组arr[]中
先确定第一维i,既是当前位的数字,从小到大。用elementCounts[i]判断当前位的桶中是否有数据
如果当前位的桶中是有数据。那就遍历当前桶(既是当前位位的数字为i的桶)
桶的第二维为j也就是当前桶有多少数据?个数为elementCounts[i]。以其为for循环的边界,遍历bucket[i][],再放入原数组中
最后记得清空桶的记录
int index=0;//原数组下标
for (int i = 0; i <elementCounts.length ; i++) {//i用来表示该位上的数为多少
if(elementCounts[i]!=0){//elementCounts[i]用于记录该位为i的个数
for (int j = 0; j < elementCounts[i]; j++) {//j用来表示该位为i的个数
arr[index]=bucket[i][j];
index++;
}
}
//清空桶记录
elementCounts[i]=0;
}
2.5、完整代码
//基数排序
public static void jishusort(int[] arr){
//首先确定最大数值,以及位数
int max=arr[0];
for (int i = 0; i <arr.length ; i++) {
if(arr[i]>max){
max=arr[i];
}
}
int maxLength=(max+"").length();
//桶是什么,二维数组
//arr.length可能会出现一位全部相同的情况
int[][] bucket=new int[10][arr.length];
//定义一个桶记录工具
int[] elementCounts=new int[10];
int n=1;
//maxLength为位数
//h用于控制论述,通过个十白千位来控制
for (int h = 0; h < maxLength; h++) {
//循环遍历数组
for (int i = 0; i < arr.length ; i++) {
//计算当前个位十位百位的数值,element为个位,十位…………的数值
int element=arr[i]/n%10;
//读一下桶记录器当中的数据,也就是该位中
int count=elementCounts[element];//数组默认值为0,故count第一次被赋值时为0,count用于记录该位为element的个数
bucket[element][count]=arr[i];//初始值为bucket[][0]=arr[0],也就是将个位(其他位)为element的数组元素放入桶中
elementCounts[element]=elementCounts[element]+1;//elementCounts[element]最开始为0,加一用于统计某位为element的个数
}//上面的代码实现了将数放入桶中
int index=0;//原数组下标
for (int i = 0; i <elementCounts.length ; i++) {//i用来表示该位上的数为多少
if(elementCounts[i]!=0){//elementCounts[i]用于记录该位为i的个数
for (int j = 0; j < elementCounts[i]; j++) {//j用来表示该位为i的个数
arr[index]=bucket[i][j];
index++;
}
}
//清空桶记录
elementCounts[i]=0;
}
n=n*10;
}
System.out.println("排序后为:"+Arrays.toString(arr));
}