第2课_计数排序法
热度🔥:16 免费课程
授课语音
计数排序法
1. 介绍
计数排序是一种非比较排序算法,它通过统计数据中每个元素出现的次数,然后根据这些统计信息将元素排成有序序列。与传统的基于比较的排序算法不同,计数排序不需要进行元素之间的直接比较,因此能够在特定条件下达到更高的排序效率。
1.1 计数排序的基本思想:
计数排序的基本思想是通过“计数”的方式来代替比较。它适用于数据范围比较小的情况。当数据范围不是很大时,计数排序的效率可能比常见的比较排序算法(如快速排序、归并排序)更高。计数排序的工作流程大致如下:
- 确定数据的范围:首先找出数据中的最大值和最小值,从而确定数据的取值范围。
- 创建计数数组:根据数据的取值范围,创建一个计数数组,用于统计每个数字出现的次数。
- 统计频次:遍历原始数组,根据每个元素的值在计数数组中进行计数。
- 生成排序数组:根据计数数组的统计结果,将元素按顺序放入输出数组,得到有序数组。
1.2 计数排序的适用条件:
- 数据的范围(最大值和最小值的差距)相对较小。
- 数据的分布较为均匀。
- 适用于整数排序或某些特定类型的排序(如字符排序)。
1.3 计数排序的时间复杂度:
- 时间复杂度:O(n + k),其中n是待排序元素的个数,k是数据范围的大小(最大值与最小值之差)。
- 空间复杂度:O(k),需要额外的空间来存储计数数组。
计数排序是一种稳定的排序算法。稳定的排序算法意味着相等元素的相对顺序在排序后不会改变,这对于某些应用场景(例如多重排序)非常有用。
2. 代码案例
下面是使用Java实现计数排序的示例代码:
import java.util.Arrays;
public class CountingSort {
public static void countingSort(int[] arr) {
if (arr == null || arr.length == 0) {
return; // 如果数组为空,则直接返回
}
// 找到数组中的最大值和最小值
int max = arr[0];
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i]; // 更新最大值
}
if (arr[i] < min) {
min = arr[i]; // 更新最小值
}
}
// 创建计数数组,大小为最大值与最小值之间的范围
int[] count = new int[max - min + 1];
// 统计每个元素的出现频率
for (int i = 0; i < arr.length; i++) {
count[arr[i] - min]++;
}
// 将计数数组中的元素按顺序放回原数组
int index = 0;
for (int i = 0; i < count.length; i++) {
while (count[i] > 0) {
arr[index++] = i + min; // 将当前元素放回数组
count[i]--;
}
}
}
public static void main(String[] args) {
// 示例数组
int[] arr = {4, 2, 2, 8, 3, 3, 1};
// 输出排序前的数组
System.out.println("排序前: " + Arrays.toString(arr));
// 调用计数排序
countingSort(arr);
// 输出排序后的数组
System.out.println("排序后: " + Arrays.toString(arr));
}
}
2.1 代码解析:
初始化最大值和最小值: 我们首先遍历数组,找出其中的最大值和最小值。这一步是为了后续创建计数数组时,确定计数数组的大小。
创建计数数组: 根据最大值和最小值,创建一个计数数组。该数组的大小为
max - min + 1
,用于记录每个数出现的频率。统计频率: 遍历原数组,对于每个元素,更新计数数组中对应位置的值。
count[arr[i] - min]
表示元素arr[i]
出现的次数。根据计数数组生成有序数组: 遍历计数数组,根据频率将每个元素依次放入原数组中,从而得到排序后的数组。
2.2 测试结果:
对于输入数组 {4, 2, 2, 8, 3, 3, 1}
,排序后的结果将是:
排序前: [4, 2, 2, 8, 3, 3, 1]
排序后: [1, 2, 2, 3, 3, 4, 8]
3. 总结
计数排序是一种基于计数的排序方法,通过统计每个元素的出现次数来实现排序。它适用于数据范围较小的情况,能够在某些场景下显著提高排序效率。需要注意的是,计数排序不能用于处理负数,并且数据范围较大时需要消耗较大的空间,因此它的适用场景有一定限制。在实际使用时,结合数据的特性来选择合适的排序算法非常重要。
- 适用场景:数据范围小,元素分布均匀的情况。
- 时间复杂度:O(n + k),其中n是元素个数,k是数据范围的大小。
- 空间复杂度:O(k),需要额外的计数数组空间。
计数排序通过其高效的计数机制,在一些特定场景中能提供比比较排序更快的性能,但也有一些使用限制。了解这些特性后,能够在合适的场景下充分发挥计数排序的优势。