学习过比较排序后,接下来继续整理非比较排序的内容。比较排序算法复杂度最低为O(nlogn),而非比较排序,时间复杂度都要更好一些,为O(n),但都有其特定的适用场景,今天先从计数排序说起。
计数排序(Counting-sort)
计数排序(也称为桶排序),顾名思义,是通过统计序列中元素出现的次数来排序,适用范围是排序序列中的所有元素,都小于某个固定的不大的值,官方严谨的定义如下:
计数排序假设n个输入元素中的每一个都是0到k区间内的一个整数,其中k为某个整数。当k=O(n)时,排序的运行时间为O(n)
动态演示图点此查看
计数排序的基本思想是:初始化一个k+1个元素的数组,分别存放对应位置数值在元素中出现的个数,再修改为小于对应位置数值元素的总个数,再遍历原数组,将遍历值填充到输出结果数组,注意遍历过程中是从原始数组的末位开始的,这样可以实现稳定的(即原始数组中存在相等元素时排序后的序列其相对位置不变)输出结果
代码实现如下:
import java.util.Arrays;
public class CountingSort {
public static void main(String[] args) {
int[] arr = new int[]{2, 5, 3, 0, 2, 3, 0, 3};
System.out.println("before counting sort, the array is: ");
System.out.println(Arrays.toString(arr));
int[] result = countingSort(arr, 5);
System.out.println("\nend counting sort, the array is: ");
System.out.println(Arrays.toString(result));
}
private static int[] countingSort(int[] original, int k) {
int[] tempK = new int[k + 1];
int[] result = new int[original.length];
for (int i = 0; i < original.length; i++) {
tempK[original[i]] += 1;
}
for (int i = 1; i < tempK.length; i++) {
tempK[i] = tempK[i] + tempK[i - 1];
}
for (int j = original.length - 1; j >= 0; j--) {
result[tempK[original[j]] - 1] = original[j];
tempK[original[j]] -= 1;
}
return result;
}
}
小结
计数排序算法虽然看起来比较简单,但实现过程中还是有很多细节需要注意的,比如中间临时数组下标位置与原始数组值的对应,以及为了实现稳定的排序,最后的遍历要从原始数组的末尾开始等。
参考资料:
《算法导论》
系列示例代码下载:欢迎关注我的github