C#计数排序算法

举报
Rolle 发表于 2024/10/31 00:03:02 2024/10/31
【摘要】 计数排序(Counting Sort)是一种非比较型整数排序算法,其核心在于将输入的数字映射到数组索引上。与传统排序算法相比,计数排序在处理特定类型的数据时(如整数或小范围的值)具有非常高的效率。该算法的时间复杂度通常为O(n + k),其中n是待排序数组中的元素数量,k是数组中最大和最小元素的差值。计数排序的基本原理计数排序的基本思想是:对于给定的一组数据,我们首先统计每个值出现的次数,然...

计数排序(Counting Sort)是一种非比较型整数排序算法,其核心在于将输入的数字映射到数组索引上。与传统排序算法相比,计数排序在处理特定类型的数据时(如整数或小范围的值)具有非常高的效率。该算法的时间复杂度通常为O(n + k),其中n是待排序数组中的元素数量,k是数组中最大和最小元素的差值。

计数排序的基本原理
计数排序的基本思想是:对于给定的一组数据,我们首先统计每个值出现的次数,然后根据这些计数来确定每个元素在排序后数组中的位置。算法的步骤如下:

找出待排序数组中的最大值和最小值。
创建一个新的数组,其长度为最大值和最小值之差加一。
遍历原数组,对于数组中的每个元素,将其对应的计数数组元素加一。
再次遍历计数数组,将每个元素累加,从而得到每个值在排序后数组中的最终位置。
根据计数数组构建排序后的数组。
计数排序的算法步骤
确定最大值和最小值:首先遍历整个数组,找到最大值和最小值。
创建计数数组:初始化一个长度为最大值和最小值之差的数组,并将其所有元素设置为0。
填充计数数组:再次遍历原数组,对于数组中的每个元素,将其对应的计数数组元素加一。
累加计数数组:对计数数组进行累加,从而得到每个值在排序后数组中的最终位置。
构建排序数组:根据累加后的计数数组构建排序后的数组。
计数排序的C#实现
下面是一个计数排序算法的C#实现示例:
using System;

class Program
{
static void CountingSort(int[] arr)
{
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 range = max - min + 1;
    int[] count = new int[range];
    int[] output = new int[arr.Length];
    
    // 初始化计数数组
    for (int i = 0; i < arr.Length; i++)
    {
        count[arr[i] - min]++;
    }

    // 累加计数数组
    for (int i = 1; i < count.Length; i++)
    {
        count[i] += count[i - 1];
    }

    // 构建排序数组
    for (int i = arr.Length - 1; i >= 0; i--)
    {
        output[count[arr[i] - min] - 1] = arr[i];
        count[arr[i] - min]--;
    }

    // 将排序后的数组复制回原数组
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = output[i];
    }
}

static void Main()
{
    int[] arr = { 4, 2, 2, 8, 3, 3, 1 };
    int n = arr.Length;

    Console.WriteLine("Given array is ");
    foreach (int value in arr)
    {
        Console.Write(value + " ");
    }

    CountingSort(arr);

    Console.WriteLine("\nSorted array is ");
    foreach (int value in arr)
    {
        Console.Write(value + " ");
    }
}

}
在这个示例中,我们首先定义了一个未排序的整数数组arr。然后,我们使用CountingSort方法对数组进行排序。CountingSort方法首先找出数组中的最大值和最小值,然后创建并初始化计数数组,接着填充计数数组并累加计数,最后根据累加后的计数数组构建排序后的数组。

计数排序的性能分析
计数排序的时间复杂度通常为O(n + k),其中n是待排序数组中的元素数量,k是数组中最大和最小元素的差值。由于计数排序不是基于比较的排序算法,因此它在处理特定类型的数据时(如整数或小范围的值)具有非常高的效率。

计数排序的空间复杂度是O(k),因为我们需要额外的存储空间来存储计数数组。

计数排序的优化
尽管计数排序在特定情况下非常高效,但在某些情况下,其性能可能会受到影响。例如,当k的值非常大时,计数排序的空间复杂度会很高。为了优化计数排序,可以采取以下措施:

使用更小的基数:如果数据的范围非常大,可以考虑使用基数为2或4的计数排序,这样可以减少计数数组的大小。
使用线性计数数组:对于小范围的值,可以使用线性计数数组来减少空间复杂度。
与其他排序算法结合:对于大数据集,可以先使用快速排序或归并排序对数据进行粗略排序,然后再使用计数排序进行精细排序。
下面是一个优化后的计数排序算法的C#实现示例,使用线性计数数组:
using System;

class Program
{
static void CountingSort(int[] arr, int max)
{
int[] count = new int[max + 1];
int[] output = new int[arr.Length];

    // 初始化计数数组
    for (int i = 0; i < arr.Length; i++)
    {
        count[arr[i]]++;
    }

    // 累加计数数组
    for (int i = 1; i < count.Length; i++)
    {
        count[i] += count[i - 1];
    }

    // 构建排序数组
    for (int i = arr.Length - 1; i >= 0; i--)
    {
        output[count[arr[i]] - 1] = arr[i];
        count[arr[i]]--;
    }

    // 将排序后的数组复制回原数组
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = output[i];
    }
}

static void Main()
{
    int[] arr = { 4, 2, 2, 8, 3, 3, 1 };
    int max = 8; // 假设我们知道最大值

    Console.WriteLine("Given array is ");
    foreach (int value in arr)
    {
        Console.Write(value + " ");
    }

    CountingSort(arr, max);

    Console.WriteLine("\nSorted array is ");
    foreach (int value in arr)
    {
        Console.Write(value + " ");
    }
}

}
在这个优化后的示例中,我们使用线性计数数组来减少空间复杂度。

计数排序的应用场景
计数排序适用于以下场景:

数据范围较小:当数据范围较小时,计数排序的空间复杂度较低,效率较高。
大量重复数据:当数据集中存在大量重复数据时,计数排序可以快速完成排序。
非负整数排序:计数排序适用于非负整数的排序,特别是当数据范围较小时。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。