目录
计数排序
计数排序是对存在有限较短的情况的数组进行排序,可以将数组中每一个数出现的频率进行统计,从而达到排序。
public static void countSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}//如果数组为空或者数组的长度为1,直接返回
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
max = Math.max(max, arr[i]);
}//求出数组中的最大值
int[] bucket = new int[max + 1];//建立一个长度为最大值加1的辅助数组
for (int i = 0; i < arr.length; i++) {
bucket[arr[i]]++;
}//对数组中每一个数出现的频率进行统计
int i = 0;
for (int j = 0; j < bucket.length; j++) {
while (bucket[j]-- > 0) {
arr[i++] = j;//按照关键词的位序依次输出排好序的数,放到原数组
}
}
}
上面代码的时间复杂度为,对于情况较少的数组排序比较快,但是对于情况较多的排序,时间复杂度较高,根据情况进行选择。
基数排序
基数排序是一种很特别的排序方法,它不基于比较和移动进行排序,而是基于关键词各位的大小进行排序。例如对于一串数字,100,28,89,46,128,首先找到最大的数字,将他的位数作为最终的位数,其它位数不够的数字前面补0。然后将所有的数字分别按照个位数,十位数,百位数从小到大排列,最终的数组就是排好序的数组。
代码的实现对操作进行了一定的优化,代码如下:
public static void radixSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;//如果数组为空或者数组的长度为1,直接返回
}
radixSort(arr, 0, arr.length - 1, maxbits(arr));//maxbits(arr)表示数组中最大值的位数
}
public static int maxbits(int[] arr) {//求出数组中最大值的位数
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
max = Math.max(max, arr[i]);
}
int res = 0;
while (max != 0) {
res++;
max /= 10;
}
return res;
}
public static void radixSort(int[] arr, int begin, int end, int digit) {
final int radix = 10;//每一位最多有十个不同的数字,以10为基底
int i = 0, j = 0;
int[] bucket = new int[end - begin + 1];//准备一个辅助数组和原数组长度相同
for (int d = 1; d <= digit; d++) {//有多少位就进出几次
int[] count = new int[radix];//10个空间
for (i = begin; i <= end; i++) {//从数组的开始位置开始到结束位置,依次提取数组中每一个数的相应位数的数值
j = getDigit(arr[i], d);//提取数组中数的第d位的数
count[j]++;//数字为j的数量加1
}
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];//将统计出来的每一位数字出现的频数的数组依次累加
}
for (i = end; i >= begin; i--) {
j = getDigit(arr[i], d);
bucket[count[j] - 1] = arr[i];
count[j]--;
}//对于原始数组从end位置开始往回,对每一个数,从个位数开始,进行排序,根据数字找到相应的数字频数-1的对应辅助数组的位置就是对应的位置
for (i = begin, j = 0; i <= end; i++, j++) {
arr[i] = bucket[j];//上述循环完毕将辅助数组排好序的数字复制回原数组
}
}
}
public static int getDigit(int x, int d) {
return ((x / ((int) Math.pow(10, d - 1))) % 10);
}//提取一个数字d位的数字
上面程序的时间复杂度为,空间复杂度为(M表示根据关键词的情况对空间进行调用)。
总结
对于这种不基于比较和移动的排序,一定要根据具体的排序情况和特征对排序的程序进行编写,没有普遍适用的,而其中最重要的排序就是基数排序。