计数排序假设n个输入元素中的每一个都是在0到k区间的一个整数,其中k为某个整数,当k=O(n)时,排序的运行时间为θ(n)。
计数排序的基本思想是:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输出数组中的位置上。例如,如果有17个元素小于x,则x就应该在第18个输出位置上。根据这个思想,对于一个A[1…n]的数组,计数排序可按如下步骤进行:
- 定义一个数组B[1…n],用于存放最终排序的A中的元素;
- 计算出数组A中的最大值k;
- 定义数组C[0…k],用于存放A中元素的计数;
- 对数组A中的元素进行计数,并将A中元素的计数放到C中以该元素为下标的位置;
- 计数完成后,对C中的元素进行加总,使得C[i]=C[i]+C[i-1];
- 最后,根据C中的结果将A中对应的元素放置到B中对应的位置。
下图展示了计数排序的运行过程:
java实现如下:
/**
* 计数排序
*
* @param nums 待排序数组
*/
public void countingSort(int[] nums) {
// 定义临时数组用于存放排序后的结果
int[] tempResult = new int[nums.length];
// 计算数组中的最大值,用于定义计数数组
int max = Integer.MIN_VALUE;
for (int num : nums) {
max = Math.max(max, num);
}
// 定义计数数组,并开始计数
int[] count = new int[max + 1];
for (int num : nums) {
count[num] += 1;
}
// 计算对于数组中的每一个数字k,小于等于k的个数
for (int j = 1; j <= max; j++) {
count[j] += count[j - 1];
}
// 将每个元素放到结果数组中正确排序的位置
for (int j = nums.length - 1; j >= 0; j--) {
tempResult[count[nums[j]] - 1] = nums[j];
count[nums[j]]--;
}
// 将结果数组复制到原数组
System.arraycopy(tempResult, 0, nums, 0, nums.length);
}