文章目录
- 计数排序(Counting Sort)详解
- 一、基本思想
- 1. 基本原理
- 2. 适用场景
- 3. 稳定性
- 二、实现步骤
- 1. 统计频率
- 2. 累积频率
- 3. 构建输出数组
- 4. 复制回原数组
- 三、代码实现
- 四、时间复杂度分析
- 五、空间复杂度分析
- 六、计数排序的优缺点
- 七、总结
计数排序(Counting Sort)详解
计数排序(Counting Sort)是一种非比较型排序算法,适用于整数排序。它通过计算每个元素出现的次数来确定它们在输出数组中的位置,从而实现排序。计数排序的时间复杂度为O(n + k),其中n是输入数据的数量,k是输入数据的范围大小。由于其线性时间复杂度,计数排序在处理特定类型的数据时非常高效。
本文将详细介绍计数排序的基本思想、实现步骤、代码示例以及其优缺点。
一、基本思想
1. 基本原理
计数排序的核心思想是通过统计每个元素出现的次数来确定它们在输出数组中的位置。具体步骤如下:
- 统计频率:遍历输入数组,统计每个元素出现的次数。
- 累积频率:计算累积频率,即每个元素在输出数组中的最终位置。
- 构建输出数组:根据累积频率,将输入数组中的元素放置到输出数组的正确位置。
2. 适用场景
计数排序特别适用于以下场景:
- 输入数据为整数且范围较小。
- 数据分布较为集中,不会出现极端的大或小值。
- 需要稳定的排序算法(即相同值的相对顺序保持不变)。
3. 稳定性
计数排序是一种稳定排序算法,这意味着具有相同值的元素在排序后的相对顺序与排序前相同。这在某些应用场景中非常重要,例如按多个键进行排序时。
二、实现步骤
以下是计数排序的一个详细实现步骤:
1. 统计频率
首先,创建一个计数数组count[]
,用于存储每个元素出现的次数。假设输入数据的范围是从0
到k
,则count[]
的大小为k + 1
。
2. 累积频率
对计数数组进行累积求和,得到每个元素在输出数组中的最终位置。具体来说,count[i]
表示小于等于i
的所有元素的总数。
3. 构建输出数组
根据累积频率,将输入数组中的元素放置到输出数组的正确位置。为了保证稳定性,我们从后向前遍历输入数组,并根据累积频率确定每个元素的最终位置。
4. 复制回原数组
最后,将输出数组复制回原数组,完成排序。
三、代码实现
以下是计数排序的一个Java实现示例:
java">public static void countingSort(int[] arr) {int max = max(arr);int[] cnt = new int[max + 1];// 统计每个元素出现的次数for (int i = 0; i < arr.length; i++) {cnt[arr[i]] ++;}int index = 0;// 根据统计结果构建排序结果for (int i = 0; i <= max; i++) {while(cnt[i] > 0) {arr[index ++] = i;cnt[i] --;}}
}public static int max(int[] arr) {int max = arr[0];for (int i = 1; i < arr.length; i++) {if(arr[i] > max) {max = arr[i];}}return max;
}
四、时间复杂度分析
计数排序的时间复杂度主要由以下几部分组成:
- 统计频率:遍历输入数组,统计每个元素出现的次数,时间复杂度为O(n)。
- 累积频率:遍历计数数组,计算累积频率,时间复杂度为O(k)。
- 构建输出数组:根据累积频率,将输入数组中的元素放置到输出数组的正确位置,时间复杂度为O(n)。
- 复制回原数组:将输出数组复制回原数组,时间复杂度为O(n)。
综上所述,计数排序的总时间复杂度为O(n + k)。
五、空间复杂度分析
计数排序的空间复杂度主要取决于计数数组的大小,计数数组的大小为k + 1,因此空间复杂度为O(k)。
六、计数排序的优缺点
- 优点:
- 缺点:
- 适用范围有限:计数排序仅适用于整数排序,且数据范围不能过大。如果数据范围过大(即k远大于n),则计数排序的效率会大大降低。
- 额外空间需求:计数排序需要额外的空间来进行计数,尤其是在处理大范围数据时,可能会占用较多内存。
七、总结
计数排序是一种高效的非比较型排序算法,特别适用于处理整数且范围较小的数据集。通过统计每个元素出现的次数并使用累积频率来确定它们在输出数组中的位置,计数排序能够在O(n + k)的时间复杂度内完成排序任务。尽管其适用范围有限,但在特定场景下,计数排序能够提供显著的性能优势。