计数排序(Counting Sort)是一种非比较型整数排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,它要求输入的数据必须是有确定范围的整数。
以下是计数排序算法的C#实现:
using System;
class Program
{
static void Main(string[] args)
{
int[] arr = { 4, 2, 2, 8, 3, 3, 1 };
// 调用计数排序
CountingSort(arr);
Console.WriteLine("Sorted array: ");
foreach (int num in arr)
{
Console.Write(num + " ");
}
Console.WriteLine();
}
// 计数排序方法
static void CountingSort(int[] arr)
{
if (arr.Length == 0)
return;
// 找到数组中的最大值,以确定计数数组的大小
int max = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] > max)
max = arr[i];
}
// 创建计数数组,并初始化为0
// 计数数组的大小为最大值+1,因为数组索引是从0开始的
int[] count = new int[max + 1];
// 计算每个元素的出现次数
for (int i = 0; i < arr.Length; i++)
{
count[arr[i]]++;
}
// 更改count[i],现在它包含实际的位置信息
// 注意,这里是从后往前累加,以确保稳定性
for (int i = 1; i <= max; i++)
{
count[i] += count[i - 1];
}
// 构建输出数组arr_copy,并填充排序后的数据
// 从后向前遍历输入数组,根据计数数组的值,将元素放到正确的位置
int[] arr_copy = new int[arr.Length];
for (int i = arr.Length - 1; i >= 0; i--)
{
// 将元素放到arr_copy中正确的位置
// 然后递减count[arr[i]]的值,以确保相同元素的稳定性
arr_copy[count[arr[i]] - 1] = arr[i];
count[arr[i]]--;
}
// 将排序后的数据复制回原数组
for (int i = 0; i < arr.Length; i++)
{
arr[i] = arr_copy[i];
}
}
}
在这个实现中,CountingSort
方法首先找到输入数组 arr
中的最大值,以确定计数数组 count
的大小。然后,它遍历输入数组,计算每个元素的出现次数,并将这些次数存储在计数数组中。
接下来,为了确定每个元素在输出数组中的位置,CountingSort
方法遍历计数数组,并将每个元素的值更新为其前面所有元素值的和(包括它自己)。这样,count[i]
就表示了元素 i
应该放在输出数组中的位置(索引从0开始)。
最后,CountingSort
方法通过遍历输入数组(从后往前遍历以保持稳定性),并使用计数数组来确定每个元素在输出数组中的位置,从而构建了一个排序后的数组 arr_copy
。之后,它将排序后的数据复制回原数组 arr
。
注意,计数排序的时间复杂度为 O(n+k),其中 n 是输入数组的长度,k 是输入数据的范围。这使得计数排序在数据范围不是特别大时非常高效。然而,如果 k 很大,那么计数数组可能会占用大量内存。