(1)算法简介
计数排序是一种非比较排序算法,主要用于对整数进行排序。它通过计算每个元素在数组中出现的次数来确定其在排序后数组中的位置。这种排序算法适用于元素范围较小且数据量较大的场景。
同样,我们接下来带着你边学如何实现排序算法边理解该算法的内核。
(2)算法的原理与步骤
计数排序的基本思想是创建一个计数数组,通过统计原始数组中每个元素的出现次数来确定它们在排序后数组中的正确位置。具体步骤如下:
计算最大值和最小值: 确定数组中的最大值和最小值,进而决定计数数组的大小。
计数: 创建一个计数数组,将每个元素出现的次数记录在计数数组中。
累加计数: 对计数数组中的值进行累加,以便确定每个元素的最终位置。
构建排序数组: 遍历原始数组,通过计数数组确定每个元素在排序后数组中的位置,构建最终的有序数组。
——接下来让我们使用代码来实现一下计数排序。
(3)Java代码实现
public void countSort(int[] array) {
// 初始化最小值和最大值为数组的第一个元素
int min = array[0];
int max = array[0];
// 遍历数组,找到最小值和最大值
for (int i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
if (array[i] > max) {
max = array[i];
}
}
// 创建计数数组,用于统计每个元素出现的次数
int[] count = new int[max - min + 1];
// 统计数组中每个元素出现的次数
for (int i = 0; i < array.length; i++) {
count[array[i] - min]++;
}
// 将排序后的元素放回原数组
int arrayIndex = 0;
for (int i = 0; i < count.length; i++) {
// 对计数数组进行处理,将每个元素根据其计数放入原数组中
while (count[i] != 0) {
array[arrayIndex++] = i + min;
count[i]--;
}
}
}
解释:
int min = array[0]; int max = array[0];:初始化最小值和最大值为数组的第一个元素。
for (int i = 0; i < array.length; i++):遍历数组,找到最小值和最大值。
int[] count = new int[max - min + 1];:创建计数数组 count,其长度为 max - min + 1,用来存储每个值的出现次数。
for (int i = 0; i < array.length; i++):遍历数组并填充计数数组。
count[array[i] - min]++:更新计数数组中的值,表示 array[i] 出现的次数。
for (int i = 0; i < count.length; i++):遍历计数数组,并将排序后的元素放回原数组中。
while (count[i] != 0):根据计数数组的值将元素放入原数组中,每个元素按照计数的次数放入对应的位置。
——这样我们就实现了计数排序算法了!!!
(4)时间复杂度和空间复杂度
时间复杂度: O(n+k)O(n + k)O(n+k),其中 nnn 是数组的长度,kkk 是数组中元素的范围(最大值与最小值之间的差值)。
空间复杂度: O(k)O(k)O(k)。计数排序需要额外的计数数组,空间复杂度与元素的范围成正比。
(5)算法的应用场景
计数排序的特点使其适用于以下场景:
数据范围较小的整数排序: 计数排序适合整数范围较小的排序任务,如考试成绩、年龄等。
需要稳定排序的场景: 计数排序是一种稳定的排序算法,适用于需要保持相同元素相对顺序的场景。
数据分布相对均匀: 如果数据分布极度不均匀,计数排序的效率会大大降低,因此适用于数据分布较为均匀的情况。