活动地址:CSDN21天学习挑战赛

正文

  • At first,我们先look一张我从某文章*的表格,来了解一下这几大算法
  • 图都看了,那我也不得不提一嘴,图里面的东西了
    • 算法效率
      在一个算法设计完成后,还需要对算法的执行情况做一个评估。一个好的算法,可以大幅度的节省运行的资源消耗和时间。在进行评估时不需要太具体,毕竟数据量是不确定的,通常是以数据量为基准来确定一个量级,通常会使用到时间复杂度和空间复杂度这两个概念。

    • 时间复杂度
      通常把算法中的基本操作重复执行的频度称为算法的时间复杂度。算法中的基本操作一般是指算法中最深层循环内的语句(赋值、判断、四则运算等基础操作)。我们可以把时问频度记为T(n),它与算法中语句的执行次数成正比。其中的n被称为问题的规模,大多数情况下为输入的数据量。

      对于每一段代码,都可以转化为常数或与n相关的函数表达式,记做f(n)。如果我们把每一段代码的花费的时间加起来就能够得到一个刻画时间复杂度的表达式,在合并后保留量级最大的部分即可确定时间复杂度,记做O(f(n)),其中的O就是代表数量级。
      常见的时间复杂度有(由低到高): O(1)、O(log2 n)、O(n)、O(n log2n)、O(n2)、o(n3)、O(2")、O(nl)。

    • 空间复杂度

    • 程序从开始执行到结束所需要的内存容量,也就是整个过程中最大需要占用多少的空间。为了评估算法本身,输入数据所占用的空间不会考虑,通常更关注算法运行时需要额外定义多少临时变量或多少存储结构。如:如果需要借助一个临时变量来进行两个元素的交换,则空间复杂度为O(1).

时间复杂度与空间复杂度的分类

时间复杂度

  • 最坏的情况
    最坏的情况莫过于,完整的遍历了整个集合,也没有找到需要找的的元素,循环执行次数与n相关,所以时间复杂度为O(n).

  • 最好的情况
    第一次循环便找到了元素,则时间复杂度为常数级O(1);

  • 平常的情况
    综合两种情况,顺序查找的时间复杂度为O(n),属于查找较慢的算法。

空间复杂度

算法不会改变原有的元素集合,只需要一个额外的变量控制索引变化,所以空间复杂度为常数级:O(1)。

计数排序

该算法的时间复杂了:O(n+k)。
该算法的空间复杂度:O(k)
稳定性: 稳定

计数排序是一种非基于比较的排序算法,我们之前介绍的各种排序算法几乎都是基于元素之间的比较来进行排序的,计数排序的时间复杂度为 O(n + m ),m 指的是数据量,说的简单点,计数排序算法的时间复杂度约等于 O(n),快于任何比较型的排序算法。

计数排序:统计小于等于该元素值的元素的个数i,于是该元素就放在目标数组的索引i位(i≥0)。

计数排序基于一个假设,待排序数列的所有数均为整数,且出现在(0,k)的区间之内。
如果 k(待排数组的最大值) 过大则会引起较大的空间复杂度,一般是用来排序 0 到 100 之间的数字的最好的算法,但是它不适合按字母顺序排序人名。
计数排序不是比较排序,排序的速度快于任何比较排序算法。
时间复杂度为 O(n+k),空间复杂度为 O(n+k)

算法的步骤如下:
1. 找出待排序的数组中最大和最小的元素
2. 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项
3. 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加)
4. 反向填充目标数组:将每个元素 i 放在新数组的第 C[i] 项,每放一个元素就将 C[i] 减去 1

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 计数排序
void CountSort(vector<int>& vecRaw, vector<int>& vecObj)
{// 确保待排序容器非空if (vecRaw.size() == 0)return;// 使用 vecRaw 的最大值 + 1 作为计数容器 countVec 的大小int vecCountLength = (*max_element(begin(vecRaw), end(vecRaw))) + 1;vector<int> vecCount(vecCountLength, 0);// 统计每个键值出现的次数for (int i = 0; i < vecRaw.size(); i++)vecCount[vecRaw[i]]++;// 后面的键值出现的位置为前面所有键值出现的次数之和for (int i = 1; i < vecCountLength; i++)vecCount[i] += vecCount[i - 1];// 将键值放到目标位置for (int i = vecRaw.size(); i > 0; i--) // 此处逆序是为了保持相同键值的稳定性vecObj[--vecCount[vecRaw[i - 1]]] = vecRaw[i - 1];
}int main()
{vector<int> vecRaw = { 0,5,7,9,6,3,4,5,2,8,6,9,2,1 };vector<int> vecObj(vecRaw.size(), 0);CountSort(vecRaw, vecObj);for (int i = 0; i < vecObj.size(); ++i)cout << vecObj[i] << "  ";cout << endl;return 0;
}
public class CountingSort implements IArraySort {@Overridepublic int[] sort(int[] sourceArray) throws Exception {// 对 arr 进行拷贝,不改变参数内容int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);int maxValue = getMaxValue(arr);return countingSort(arr, maxValue);}private int[] countingSort(int[] arr, int maxValue) {int bucketLen = maxValue + 1;int[] bucket = new int[bucketLen];for (int value : arr) {bucket[value]++;}int sortedIndex = 0;for (int j = 0; j < bucketLen; j++) {while (bucket[j] > 0) {arr[sortedIndex++] = j;bucket[j]--;}}return arr;}private int getMaxValue(int[] arr) {int maxValue = arr[0];for (int value : arr) {if (maxValue < value) {maxValue = value;}}return maxValue;}
}
def countingSort(arr, maxValue):bucketLen = maxValue+1bucket = [0]*bucketLensortedIndex =0arrLen = len(arr)for i in range(arrLen):if not bucket[arr[i]]:bucket[arr[i]]=0bucket[arr[i]]+=1for j in range(bucketLen):while bucket[j]>0:arr[sortedIndex] = jsortedIndex+=1bucket[j]-=1return arr

计数局限性

计数排序的毛病很多,我们来找找 bug 。

如果我要排的数据里有 0 呢? int[] 初始化内容全是 0 ,排毛线。

如果我要排的数据范围比较大呢?比如[ 1,9999 ],我排两个数你要创建一个 int[10000] 的数组来计数?

对于第一个 bug ,我们可以使用偏移量来解决,比如我要排[ -1,0,-3 ]这组数字,这个简单,我全给你们加 10 来计数,变成[ 9,10,7 ]计完数后写回原数组时再减 10。不过有可能也会踩到坑,万一你数组里恰好有一个 -10,你加上 10 后又变 0 了,排毛线。

对于第二个 bug ,确实解决不了,如果是[ 9998,9999 ]这种虽然值大但是相差范围不大的数据我们也可以使用偏移量解决,比如这两个数据,我减掉 9997 后只需要申请一个 int[3] 的数组就可以进行计数。

1.当数列最大最小值差距过大时,并不适用于计数排序

比如给定 20 个随机整数,范围在 0 到 1 亿之间,此时如果使用计数排序的话,就需要创建长度为 1 亿的数组,不但严重浪费了空间,而且时间复杂度也随之升高。

2.当数列元素不是整数时,并不适用于计数排序

如果数列中的元素都是小数,比如 3.1415,或是 0.00000001 这样子,则无法创建对应的统计数组,这样显然无法进行计数排序。

正是由于这两大局限性,才使得计数排序不像快速排序、归并排序那样被人们广泛适用。

由此可见,计数排序只适用于正整数并且取值范围相差不大的数组排序使用,它的排序的速度是非常可观的。

c++十大排序之计数排序相关推荐

  1. 十大排序算法——计数排序

    计数排序 一. 计数排序介绍 二. 计数排序基础版 三. 计数排序改进版 四. 优化最终版本_空间节省 一. 计数排序介绍 计数排序(Counting sort)是一种稳定的排序算法.计数排序使用一个 ...

  2. 八十五、再探希尔排序,桶排序,计数排序和基数排序

    @Author:Runsen 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. ---- Runsen 关于排序,其实还有很多,比如常见的希尔排序,桶排序,计数排序和基数排 ...

  3. 排序算法:桶排序、计数排序、基数排序

    相关博客: 排序算法:冒泡排序.插入排序.选择排序.希尔排序 排序算法:归并排序.快速排序 排序算法:桶排序.计数排序.基数排序 排序算法:堆排序 十大排序算法小结 这篇博客将主要介绍三种时间复杂度是 ...

  4. 排序算法---计数排序(java版)

    计数排序 原理 计数排序(Counting Sort) 使用了一个额外的数组 C,其中第 i 个元素是待排序数组A 中值等于 i 的元素的个数.然后根据数组 C 来将 A 中的元素排到正确的位置.其实 ...

  5. 数据结构—排序算法总结(插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、合并排序、计数排序)

    *排序 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性 在待排序的数组中,如果出现多个相同的关键字,例如:98751555512,中出现重复的数字,在 ...

  6. 三种线性排序算法 计数排序、桶排序与基数排序—— 转自:BYVoid

    三种线性排序算法 计数排序.桶排序与基数排序 [非基于比较的排序] 在计算机科学中,排序是一门基础的算法技术,许多算法都要以此作为基础,不同的排序算法有着不同的时间开销和空间开销.排序算法有非常多种, ...

  7. 排序算法——计数排序详解

    在排序的最终结果中,各元素的次序依赖于它们之间的比较.这类排序算法被称为比较排序.对于包含 nnn 个元素的输入序列来说,任何比较排序算法在最坏情况下都要经过至少 O(nlogn)O(n\ log\ ...

  8. 【算法自由之路】前缀树 桶排序之计数排序和基数排序

    [算法自由之路]前缀树 & 桶排序之计数排序和基数排序 前缀树(字典树) 首先是前缀树,前缀树是由字符构成的树结构,它记录有多少前缀字符通过,以及有多少个同样的字符串,其找这类信息的时间复杂度 ...

  9. 算法笔记-桶排序代码与原理、非比较排序、计数排序、基数排序、C#代码

    1. 计数排序 原理: 计数排序需要用到桶,其核心是不通过比较来获得数的大小,以桶的方式存数来计数 举例来说,一个数组是{3 2 2 1 3 5},共6个数,那么我们需要准备5个有序桶,即1号桶.2号 ...

最新文章

  1. 以不变应万变:因果启发的稳定学习年度研究进展(下篇)
  2. 软件项目风险评估报告00
  3. win10改计算机用户名,win10系统修改本地账号用户名的操作方法
  4. go 连接服务器 并存放图片_基于 Go 语言开发在线论坛(二):通过模型类与MySQL数据库交互...
  5. Python小白的数学建模课-03.线性规划
  6. 牛客 —— 湖南大学第十六届程序设计竞赛(重现赛)
  7. Ubuntu下RabbitMQ安装
  8. IDEA安装插件的两种方式
  9. 产品的思维与技术的思维差异
  10. 腾讯 云通信 如何启动Demo
  11. 破解Esxi服务器中Windows虚机密码(Esxi服务器Windows虚拟机忘记密码解决方案)
  12. python 刷 阅读量
  13. htmlunit 使用代理IP
  14. hihocoder1383 The Book List 字典树
  15. 米的换算单位和公式_Excel 怎样进行单位换算,excle怎么把米换算公里
  16. JavaScript 千分位 货币格式化
  17. yaffs2的补丁文件patch-ker分析
  18. 250部世界公认的经典大片
  19. win10消息推送服务器,推送--Win10系统 - Win10系统官方网站
  20. 工作不要太拼命,领导不会感动的!

热门文章

  1. 纯前端vue利用docxtemplater实现生成word文档下载 word模板,勾选框的默认勾选。。
  2. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(4) - 轮询Flash配置参数
  3. 什么专业可以通过培训快速进入IC行业
  4. 使用html5-qrcode 扫描二维码(vue3)
  5. Deep Reinforcement Learning amidst Lifelong Non-Stationarity
  6. 为什么您公司的工作周报制度,形同虚设?
  7. 数据结构(一)逻辑结构和存储结构
  8. java url是什么_什么是 URL?
  9. 乱弹围棋棋手_拔剑-浆糊的传说_新浪博客
  10. [普通物理] 简谐运动以及例题