算法基础:排序算法:计数排序

缺乏、安全感 2022-12-18 13:57 261阅读 0赞

在这里插入图片描述
计数排序也被称为桶排序或者箱排序,都是它和常规的桶排序还是有较为明显的区别,在这篇文章中还是使用计数排序的称呼。计数排序可以进一步将排序的时间复杂度降低到O(n),而且也可以是稳定的排序,理解起来也很容易,实现简单。它算是空间换时间策略的代表之一,空间消耗过大,受排序序列的影响极大,能够排序的场合受限,这些也都是计数排序的阿喀琉斯之踵(或许类比失当,计数排序也很难称得上是排序之中的阿喀琉斯)。

目录

  • 算法思路
  • 算法要点
  • 模拟实现
  • 结果验证
  • 算法限制

算法思路

  • 计数排序在理解上大概是比冒泡排序还要简单的排序,它的做法就是根据待排序的内容生成一大块连续的空间,能够保存待排序的最大值-最小值的范围,然后巧妙的将值作为下标进行保存,而该下标的元素中保持记录重复的次数,然后输出的时候根据顺序进行输出,有计数值的按照计数值进行输出即可,有重复的根据计数值进行递减。

算法要点

简单的计数排序模拟几乎没有什么要点:

  • 额外空间:预备一个大的空间,能将输入的范围都保存进去
  • 循环计数:对于待排序的元素进行循环,将带排序的元素的值作为下标,在额外空间的数组中进行计数
  • 结果输出:对额外空间的数组进行循环,有计数值的递减输出即可。

模拟实现

  1. void count_sort(int* arr, int num, int* count) {
  2. for (int i=0; i<num; i++) {
  3. count[arr[i]]++;
  4. }
  5. }

结果验证

加上打印和调用的示例代码,可以使用如下方式进行验证

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #define MAX_ARRAY_LENGTH 10000
  5. void count_sort(int* arr, int num, int* count) {
  6. for (int i=0; i<num; i++) {
  7. count[arr[i]]++;
  8. }
  9. }
  10. void print_array(int* count) {
  11. for (int i=0; i<MAX_ARRAY_LENGTH; i++) {
  12. for (int j=count[i]; j>0; j--) {
  13. printf("%d ",i);
  14. }
  15. }
  16. printf("\n");
  17. }
  18. int main() {
  19. int n = 0;
  20. while (scanf("%d",&n) != EOF) {
  21. int count[MAX_ARRAY_LENGTH] = { 0 };
  22. int* array = (int *)malloc(sizeof(int)*n);
  23. memset(array,0,sizeof(int)*n);
  24. for (int i=0; i<n; i++) {
  25. scanf("%d",&array[i]);
  26. }
  27. count_sort(array,n,count);
  28. print_array(count);
  29. free(array); array= NULL;
  30. }
  31. }

执行结果示例

  1. 9
  2. 9 8 7 6 5 4 3 2 1
  3. 1 2 3 4 5 6 7 8 9

注:此处算法的稳定性并未得到实现,算法本身是能够实现稳定性的,实际上为了保证稳定性,应该倒序出数或者引入新的空间,但是此处只是模拟排序的介绍,并未做过多延伸。

算法限制

计数排序在有限的范围内使用效果较好,但是很明显的有如下限制:

  • 因为利用连续空间,可能造成极大浪费空间而且范围受限,比如上述例子只能排序10000之内的正整数
  • 直接不作处理的话无法排序小数和负数
  • 受数据影响非常之大,比如1000万个1-100的数字排序,效果会非常好,但是极端来看1 1000000000的两个序列的排序,效率会非常之差

发表评论

表情:
评论列表 (有 0 条评论,261人围观)

还没有评论,来说两句吧...

相关阅读