计数排序(Counting Sort)是一种简单的排序算法,其基本思想是通过统计每个元素出现的次数,然后根据次数对元素进行排序。下面是计数排序的基本步骤:
- 确定计数数组的长度:计数数组的长度应该大于等于待排序数组中最大元素的值。例如,如果待排序数组的范围是 0 到 99,那么计数数组的长度可以设置为 100。
- 统计每个元素出现的次数:遍历待排序数组,对于每个元素,将其值作为索引,将计数数组中对应位置的元素值加 1。
- 计算每个元素的排序索引:遍历计数数组,将每个元素的值减去 1,得到每个元素的排序索引。
- 重新排序待排序数组:根据计算得到的排序索引,遍历待排序数组,将每个元素放到其对应的排序索引位置上。
动画演示
下面为各编程语言实现计数排序的方法
C语言
#include<stdio.h>
#include<stdlib.h>
/* 计数排序函数 */
void CountingSort(int *arr, int n){
// 计算出计数数组所需空间大小
int max = arr[0], min = arr[0];
for (int i = 0; i < n; i++){
if (arr[i] > max)
max = arr[i];
if (arr[i] < min)
min = arr[i];
}
// 初始化计数数组(原始数组:arr[],计数数组:count_arr[])
int range = max - min + 1;
int *count_arr = (int *)calloc(range, sizeof(int));
// 原始数组中每个数分别出现了多少次
for (int i = 0; i < n; i++)
count_arr[arr[i] - min] += 1; // 防止数组越界
int j = 0;
// 根据统计结果,重新对元素进行回收
for (int i = 0; i < range; i++){
while (count_arr[i]--)
arr[j++] = i + min;
}
free(count_arr); // 释放计数数组
count_arr = NULL;
}
/* 打印数组函数 */
void PrintArray(int *arr, int n){
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
putchar(10);
}
int main(){
int arr[] = {3, 9, 9, 6, 2, 1, 3, 4, 3, 8};
int n = sizeof(arr) / sizeof(int); // 求数组长度
printf("排序前的数组:");
PrintArray(arr, n);
CountingSort(arr, n);
printf("排序后的数组:");
PrintArray(arr, n);
return 0;
}
C++
#include<iostream>
using namespace std;
/* 计数排序类 */
class Counting_Sort{
public:
// 对输入的整数数组进行计数排序
int* CountingSort(int* arr, int n){
// 如果输入的数组 arr 为空指针或者数组长度 n 小于等于 0,则返回空指针
if (arr == nullptr || n <= 0)
return nullptr;
// 初始化最大值和最小值
int max = arr[0];
int min = arr[0];
// 寻找原始数组最大值和最小值
for (int i = 1; i < n; ++i){
if (arr[i] > max)
max = arr[i];
if (arr[i] < min)
min = arr[i];
}
// 计算最大值和最小值之间的差值
int dif = max - min;
// 分配一个长度为 差值+1 的整数数组 count_arr 用于存储数组 arr 中各元素出现的次数
int* count_arr = new int[dif + 1];
for (int i = 0; i <= dif; ++i)
count_arr[i] = 0;
// 遍历原始数组,统计每个元素出现的次数
for (int i = 0; i < n; ++i)
++count_arr[arr[i] - min];
// 计算累计次数
for (int i = 1; i <= dif; ++i)
count_arr[i] += count_arr[i - 1];
// 分配一个长度为原始数组长度的整数数组 sorted_arr 用于存储排序后的元素
int* sorted_arr = new int[n];
// 从后往前遍历原始数组,将元素插入到已排序的部分
for (int i = n - 1; i >= 0; i--){
sorted_arr[count_arr[arr[i] - min] - 1] = arr[i];
count_arr[arr[i] - min]--;
}
return sorted_arr;
}
};
int main(){
int arr[] = {3, 9, 9, 6, 2, 1, 3, 4, 3, 8};
int n = sizeof(arr) / sizeof(int); // 求数组长度
cout << "排序前的数组:";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
Counting_Sort M;
int* sorted_arr = M.CountingSort(arr, n);
cout << endl << "排序后的数组:";
for (int i = 0; i < n; ++i)
cout << sorted_arr[i] << " ";
return 0;
}
Python
''' 计数排序函数 '''
def CountingSort(arr):
# 找到数组中的最大值,创建一个长度为最大值加 1 的空列表,用于存储每个元素的计数
max_num = max(arr)
count_arr = [0 for _ in range(max_num + 1)]
# 遍历数组,将元素的值作为索引,将其对应的计数加 1
for value in arr:
count_arr[value] += 1
# 创建一个存储排序后元素的空数组
sorted_arr = []
# 遍历计数数组,将对应元素放入排序后数组中
for i in range(len(count_arr)):
while count_arr[i] != 0:
sorted_arr.append(i)
count_arr[i] -= 1
return sorted_arr
arr=[3, 9, 9, 6, 2, 1, 3, 4, 3, 8]
print("排序前的数组:", ' '.join(map(str, arr)))
print("排序后的数组:", ' '.join(map(str, CountingSort(arr))))
Java
import java.util.Arrays;
public class Counting_Sort {
/* 计数排序函数 */
public static int[] CountingSort(int[] arr) {
// 找到数组中的最大值
int max_num = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max_num) {
max_num = arr[i];
}
}
// 创建一个长度为最大值加 1 的计数数组
int[] count_arr = new int[max_num + 1];
for (int i = 0; i < arr.length; i++) {
count_arr[arr[i] - 1]++;
}
// 创建一个长度与原数组相同的排序后数组
int[] sorted_arr = new int[arr.length];
int k = 0;
// 遍历计数数组,将对应元素放入排序后数组中
for (int i = 0; i < count_arr.length; i++) {
while (count_arr[i] > 0) {
sorted_arr[k++] = i + 1;
count_arr[i]--;
}
}
return sorted_arr;
}
public static void main(String[] args) {
int[] arr = {3, 9, 9, 6, 2, 1, 3, 4, 3, 8};
System.out.print("排序前的数组:");
for (int i : arr)
System.out.print(i + " ");
System.out.println();
int[] sorted_arr = CountingSort(arr);
System.out.print("排序后的数组:");
for (int i : sorted_arr)
System.out.print(i + " ");
}
}