一分钟学会计数排序——C语言实现

简介: 一分钟学会计数排序——C语言实现

image.png


前言


本章为 数据结构与算法 专栏第 21 课,欢迎小伙伴们阅读学习~


------------------------------------------------------------------------------------

本章主要内容:认识与学习计数排序;

本章学习目标:

1.熟练掌握计数排序的实现;

2.学习计数排序的思想;

gogogo!!!


目录


一、过程详解

二、代码实现

三、代码改进


正文


计数排序是一种非比较排序。它的主要思想是建立一个临时数组 CountArr ,用来统计序列中每个元素出现的次数,例如若序列元素 n 一共出现了 m 次,则使 CountArr [n] = m;统计完毕后。根据统计的结果,将序列按顺序插入到原数组中即完成排序。


一、过程详解


我相信单凭一句概念是理解不了的,接下来通过示例详细讲解;

这是待排序的数组;

11.png

这是统计数组用来统计原数组中每个元素出现的次数;

12.png

接下来进行统计;

13.png

根据统计结果在原数组中填入数据;

以上就是整个统计排序过程了。


二、代码实现


了解了过程后,代码的实现很简单。

void CountSort(int* a, int n)
{
  int max = a[0];
  for (int i = 0; i < n; i++)
  {
    if (max < a[i])
      max = a[i];
  }
  //建立临时数组,并将数组内容全部初始化为0
  int* CountArr = (int*)calloc(max+1,sizeof(int));
  if (CountArr == NULL)
  {
    perror("calloc fail");
    exit(-1);
  }
  //1.统计次数
  for (int i = 0; i <n; i++)
  {
    CountArr[a[i]]++;
  }
  //2.排序
  int k = 0;
  for (int j = 0; j <= max; j++)
  {
    while (CountArr[j]--)
    {
      a[k++] = j;
    }
  }
  free(CountArr);
}

以上代码虽然能够完成排序的任务,但是它是有缺陷的。


假设我们要排序的序列为1,6,6,6,6,9,9,3,3,5,7,8,2,3,0,0,0 ,那么效果非常棒。因为它的时间复杂度为 O(N+max),空间复杂度为 O(max+1)。


我们发现空间复杂度是与序列中的最大值 max 有关的,因为首先需要创建大小为 max+1 的统计数组。


如果我们要排序的序列为 1001,1002,1003,1003,1001,1005,1001,按照上述代码的逻辑,应该创建一个大小为 1005 +1 的统计数组。


这里就有一个很明显的弊端,序列只有 7 个元素,却要用大小 1005+1 的统计数组来统计,意味着统计数组的前 1000 位都要被浪费掉了。


那么统计数组合理的大小应为多大呢?答案是 1005 - 1001 + 1,即序列最大元素 - 最小元素 + 1。


三、代码改进


试着改进一下之前的计数排序代码。

void CountSort(int* a, int n)
{
  int max = a[0];
  int min = a[0];
  for (int i = 0; i < n; i++)
  {
    if (max < a[i])
      max = a[i];
    if (min > a[i])
      min = a[i];
  }
  int range = max - min + 1;
  int* CountArr = (int*)calloc(range,sizeof(int) );
  if (CountArr == NULL)
  {
    perror("calloc fail");
    exit(-1);
  }
  //1.统计次数
  for (int i = 0; i < n; i++)
  {
    CountArr[a[i] - min]++;
  }
  //2.排序
  int k = 0;
  for (int j = 0; j < range; j++)
  {
    while (CountArr[j]--)
    {
      a[k++] = j + min;
    }
  }
  free(CountArr);
}

改进后的统计排序,时间复杂度为O(N+range)空间复杂度为 O(range)。计数排序看着貌似比快排还要厉害,但是它的局限性较高。计数排序适合范围集中的数据,并且只适合整型数据。


目录
相关文章
|
存储 算法
玩转快速排序(C语言版)
玩转快速排序(C语言版)
78 0
|
7月前
|
C语言
C语言的简单选择排序
C语言的简单选择排序
28 0
|
7月前
|
C语言
C语言实现插入排序
C语言实现插入排序
54 0
|
7月前
|
搜索推荐 C语言
【c语言】快速排序
【c语言】快速排序
35 0
|
人工智能 算法 C语言
C语言归并排序
C语言归并排序
45 0
|
算法 C语言
【C语言】快速排序
【C语言】快速排序
181 0
|
人工智能 搜索推荐 C语言
【C语言】插入排序
【C语言】插入排序
103 0
|
算法 搜索推荐 C语言
【C语言】归并排序
【C语言】归并排序
82 0
|
算法 搜索推荐 C语言
快速排序—C语言实现
快速排序—C语言实现
105 0
|
算法 C语言
插入排序-C语言实现
插入排序-C语言实现
139 0