桶排序
不基于比较的排序,基于数据状况的排序
算法工程
1.根据待排序集合中最大元素和最小元素的差值范围和映射规则,确定申请的桶个数;
2.遍历待排序集合,将每一个元素移动到对应的桶中;
3.对每一个桶中元素进行排序,并移动到已排序集合中。
计数排序
//计数排序
public static void sort(int[] arr) {
int min = arr[0];
int max = arr[0];
//产生一个大小为数据最大值减最小值+1的辅助数组help,
for (int i = 0; i < arr.length; i++) {
min = min > arr[i] ? arr[i] : min;
max = max < arr[i] ? arr[i] : max;
}
//new出来的数组,动态初始化,默认值为0
int[] help = new int[max - min + 1];
// help[index]表示arr中值为min+index的数据个数
for (int i = 0;i<arr.length;i++){
help[arr[i]-min]++;
}
int index=0;
//辅助数组的数转变成arr中的排序
for (int i =0;i<help.length;i++){
while(help[i]-- >0){
arr[index++] = i;
}
}
}
基数排序
算法过程
前提:样本必须十进制,且非负数
- 先找出最大数,按照其位数为准,其他数据位数少的高位补零;
- 先按照低位进桶,先进先出;(队列)
- 再按照高位进桶,先进先出。
以下算法为另一种实现方式
/*
基数排序
*/
public class RadixSort {
// 对arr[L...R]进行排序,digit:最大数的十进制位数
public static void radixSort(int[] arr, int L, int R, int digit) {
//有多少个数就申请多少空间
int[] help = new int[R - L + 1];
// d代表位数,d=1代表个位 d=2 十位...
for (int d = 1; d <= digit; d++) {
//申请一个词频统计的数组
//count[i] 代表d位为i的数有多少
int[] count = new int[10];
for (int i = 0; i < R - L + 1; i++) {
int j = getDigit(arr[L+i],d);
count[j]++;
}
for (int i=1;i<10;i++){
count[i] = count[i]+count[i-1];
}
//从右到左遍历arr,后进后出,所以把其放到count[i]所对应的位置上
for(int i = R;i>L-1;i--){
int j = getDigit(arr[i],d);
help[count[j]-1] = arr[i];
count[j]--;
}
//copy回原数组
for(int i = 0;i<R-L+1;i++){
arr[i] = help[i];
}
}
}
//n求位上的数字
public static int getDigit(int num, int n) {
return (num / (int) Math.pow(10, n - 1)) % 10;
}
public static void sort(int[] arr,int L,int R){
if(arr==null||arr.length<2){
return;
}
//先找出最大位数
int max = Integer.MIN_VALUE;
for (int i = L; i < R - L + 1; i++) {
max = max > arr[i] ? max : arr[i];
}
//最大数的位数
int n = (int) Math.log10(max) + 1;
// int n = 0;
// while (max != 0) {
// res++;
// max /= 10;
// }
radixSort(arr,L,R,n);
}