鸽巢原理:揭秘计数排序的奇妙思想

简介: 鸽巢原理:揭秘计数排序的奇妙思想

一、计数排序的概念

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。以前我们选择排序的时候一般都是使用大数比较小数来进行比较

而计数排序是统计每个数字出现的个数来进行排序,哈哈哈是不是突然就发现了新大陆这个思想太奇妙了,非常值得我们学习一下他的思想

其计数排序的思想就是把每个当某个数字出现时就在其下标下面 ++ 如果没有这个数字的话就默认为零。

诶是不是非常简单要对一组数据进行排序的话我们顶多遍历三遍就可以了

  • 第一遍找到最大值进行开空间
  • 第二遍进行统计个数
  • 第三遍根据统计好的个数来直接写入

1.1 计数排序的缺陷

但是这样的话就有一个非常大的缺陷就是我们的数据多大就要开多少空间这样空间浪费的实在的是太大了:

  1. 空间开辟太大了,数值多大就得开辟多少空间
  2. 既然是使用下标进行统计排序那么肯定只能排序整数

1.2 计数排序的优化

所以我们先找出需要排序的最大值和最小值,把他们的差值标记住用于开辟空间:

当我们开空间时就只开他们差值个空间就可以了

  • 当需要统计个数的时候就把原本的数减去 最小值 来存放下标
  • 而恢复排序的时候只需要将下标加上 最小值 就可以了

这样一来性能就得到了极大的优化

二、计数排序的实现

2.1 计数排序的代码

//计数排序
void CountSort(int* a, int n)
{
  int max = 0, min = 0;
  for (int i = 0; i < n; i++)
  {
    if (a[i] > max)
    {
      max = a[i];
    }
    if (a[i] < min)
    {
      min = a[i];
    }
  }
  //开辟计数空间
  int range = max - min + 1;
  int* tmp = (int*)calloc(range,sizeof(int));
  if (tmp == NULL)
  {
    perror("calloc file");
    exit(-1);
  }
  //统计数据出现的个数
  for (int i = 0; i < n; i++)
  {
    tmp[a[i]-min]++;
  }
  //排序
  int index = 0;
  for (int i = 0; i < range; i++)
  {
    while (tmp[i])
    {
      a[index++] = i+min;
      tmp[i]--;
    }
  }
}

2.2 计数排序的惊人性能

前面我们一直在说计数排序性能好多少多少现在我们就来和快排希尔排序堆排序归并排序这些经典高性能对手来比比:

🔥 注:本次我们采用10万个随机数来进行排序,为避免随机数重复所以都加 i 。

实际性能

这里可以看到计数排序完胜,排10万个数据只需要一毫秒

  • 🔥 接下来我们看看1000万个数

这里依旧是完爆各种排序哦豁是不是,拳踢快排老师傅,脚打归并小年轻。

三、计数排序的特性总结

  1. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。
  2. 时间复杂度:O(MAX(N,范围))
  3. 空间复杂度:O(范围)
  4. 稳定性:稳定

这里需要注意的是 计数排序只适合,在一个特定范围内数据特别多的情况或者范围集中都数据性能绝对是最棒的!

🔥 注:计数排序还有一个遗憾由于是使用下标统计来排序所以只能排序整形。

目录
相关文章
|
搜索推荐
图解:快速排序算法之双边循环法
之前我们学习了冒泡排序,有没有比冒泡排序更快的排序算法呢?当然有,例如快速排序,归并排序,堆排序。接下来即将介绍的快速排序就是由冒泡排序演变而来的。
176 0
图解:快速排序算法之双边循环法
|
机器学习/深度学习 存储 算法
【数据结构与算法篇】手撕八大排序算法之快排的非递归实现及递归版本优化(三路划分)
【数据结构与算法篇】手撕八大排序算法之快排的非递归实现及递归版本优化(三路划分)
201 0
|
搜索推荐
[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)2
[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)2
|
搜索推荐
[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)1
[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)1
|
算法
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
136 0
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
|
算法
几道算法题很简单
《基础系列》
88 0
|
搜索推荐 算法
算法给小码农计数排序尊者
算法给小码农计数排序尊者
114 0
算法给小码农计数排序尊者
|
搜索推荐 算法
算法给小码农插入排序洞天,希尔排序轮回
==排序:==所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 ==稳定性:==假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。 ==内部排序:==数据元素全部放在内存中的排序。 ==外部排序:==数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。
144 0
算法给小码农插入排序洞天,希尔排序轮回
|
存储 算法 搜索推荐
八大排序算法—16张图带你彻底搞懂基数排序
原创公众号:bigsai ,16张图带你彻底搞懂基数排序,包括数字类型、等长字符类型和非等长字符类型,以及数组优化空间。
1804 0
八大排序算法—16张图带你彻底搞懂基数排序
|
算法 Python 机器学习/深度学习