只能用于整数数组。
时间复杂度均为O(n)。
1. 计数排序 Counting Sort
public static int[] countingSort(int[] A){
int[] B = new int[A.length];
int k = A[0];
//寻找数组中的最大值
for (int i = 1; i < A.length; i ++){
if (A[i] > k)
k = A[i];
}
//这个数组用来保存A数组中每个数字出现的次数
int[] C = new int[k+1];
//下面这个循环,统计各个数字在A中出现的次数
for (int i = 0 ; i < A.length ; i ++){
C[A[i]] ++;
}
//下面这个循环,将A当中 <= 元素 i 的元素数量统计出来
for (int i = 1 ; i < C.length ; i ++){
C[i] += C[i-1];
}
//将A当中的数字依次放入数组B的指定位置,使得B是排好序的A数组。逆序遍历是为了保证排序的稳定性
for (int i = A.length-1 ; i > -1 ; i--){
B[C[A[i]]-1] = A[i];
C[A[i]] --;
}
return B;
}
- 空间复杂度:O(k),k是数组中最大元素的数值。
- 计数排序是稳定排序。(不重要)
2. 基数排序
public static void radixSort(int[] A){
for (int i = 0 ; i < 32 ; i ++){
// 开辟两个ArrayList,分别存放第i位为0的数字和第i位为1的数字
List<Integer> l0 = new ArrayList<>();
List<Integer> l1 = new ArrayList<>();
// 以下涉及到二进制的运算,所以一点都不重要
for (int x : A) {
//若x的第i位为0,则将x放入l0中
if ((x >> i & 1) == 0)
l0.add(x);
//若为1,则放入l1中
else
l1.add(x);
//将第i位为0的数字,放在A数组的左半部分
for (int j = 0 ; j < l0.size() ; j ++){
A[j] = l0.get(j);
}
//将第i位为1的数字,放在A数组的右半部分
for (int j = 0 ; j < l1.size() ; j ++){
A[j+l0.size()] = l1.get(j);
}
}
}
}
- 用一句话概括:先根据个位排序,再根据十位排序,再根据百位排序。。。。。。以此类推
- 因为涉及到二进制的计算,而且这个算法在实际中没啥用,所以不会考。如果要考,那就是填空选择。例如,下图采用了哪种排序算法?(基数排序)