今天无聊就打算把所有的排序算法都看一遍。。。

  1. 计数排序的时间复杂度是O(n),在算法导论中,用决策树模型中论证了,比较排序的情况为nlogn的复杂度。而计数排序的时间复杂度小于他的原因就是它不需要进行比较。
  2. 计数排序的原理就是根据原数组(A)里面最大的元素来一个与其一样大的数组(B),新开的数组(B)的第 i 个元素的值就是 i 在原数组(A)里面出现的次数.这样就可以根据新开的数组(B)来确定原数组(A)的排序。

我们先来看看排序部分的实现:(len是数组的长度)

void countSort(int *arrayL, int len) {
int findMax = 0;
for (int i = 0; i != len; i++)
if (findMax < arrayL[i])
findMax = arrayL[i];
findMax += 1; //元素应该是从 1 开始,而数组下标是从 0 开始,所以加 1
int *sortArray = new int[findMax]; //开始设定每个元素出现的次数都为 0
for (int i = 0; i != findMax; i++)
sortArray[i] = 0; //当对应的元素出现时,个数加 1
for (int i = 0; i != len; i++)
++sortArray[arrayL[i]]; //排序
int count = 0;
for (int i = 0; i != len; i++) {
for (int j = count; j != findMax; j++) {
count++; // sortArray 中在 count 前面的元素已经遍历过了
if (sortArray[j] != 0) {
//这里 for 循环是当出现元素个数不为 1 的情况时
for (int k = 0; k != sortArray[j]; k++) {
arrayL[i++] = j; //将元素的值赋到原数组
}
i--; //for 循环里面还会自增
break;
}
}
}
}

 这部分的代码应该不难理解,因为基本都已经在代码注释说明了。这里原理就是,新开的数组的下标就是原数组的元素值。这样的话,当新开的数组某下标对应的值不为 0 时,代表该下标值在原数组出现过,而我们知道下标是有序的,那么就可以在遍历新建数组的时候有序地将有在原数组出现过的值赋给原数组。这样原数组就变得有序了。

但根据这个算法的实现我们可以看出,它并不适合当数组的元素值很大的时候。因为这样的话新开的数组空间很大,当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k),那么当K很大时,新开数组太大,既浪费空间,时间上也会有很大开销,因为虽然看上去是Θ(n + k),但当k很大时时间还是很长的。所以当需要排序的数组的元素值均在0~100之间时会比较适合。特别是当有很多元素重复的时候。另外,对于浮点数,字符串的排序他也无能为力。

其实,还有一个地方用这个算法的话会比较好,那就是在基数排序中比较每个位数的时候,因为每位数都是在0~9之间,用这个算法就很perfect了。。。

计数排序的实现--适用于元素均较小的seq的更多相关文章

  1. 计数排序(counting-sort)——算法导论(9)

    1. 比较排序算法的下界 (1) 比较排序     到目前为止,我们已经介绍了几种能在O(nlgn)时间内排序n个数的算法:归并排序和堆排序达到了最坏情况下的上界:快速排序在平均情况下达到该上界.   ...

  2. JavaScript 数据结构与算法之美 - 桶排序、计数排序、基数排序

    1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算 ...

  3. 排序算法的C语言实现(下 线性时间排序:计数排序与基数排序)

    计数排序 计数排序是一种高效的线性排序. 它通过计算一个集合中元素出现的次数来确定集合如何排序.不同于插入排序.快速排序等基于元素比较的排序,计数排序是不需要进行元素比较的,而且它的运行效率要比效率为 ...

  4. C语言-计数排序

    计数排序的基本思想是:统计一个数序列中小于某个元素a的个数为n,则直接把该元素a放到第n+1个位置上.当然当过有几个元素相同时要做适当的调整,因为不能把所有的元素放到同一个位置上.计数排序假设输入的元 ...

  5. 20191104-基于Python计数排序算法分析

    计数排序 计数排序算法没有用到元素间的比较,它利用元素的实际值来确定它们在输出数组中的位置,也就是说元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的,将每个元素出现的次数记 ...

  6. 计数排序和桶排序(Java实现)

    目录 比较和非比较的区别 计数排序 计数排序适用数据范围 过程分析 桶排序 网络流传桶排序算法勘误 桶排序适用数据范围 过程分析 比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比 ...

  7. 计数排序(Count Sort )与插入排序(Insert Sort)

    计数排序法:计数数组适用于当前数组密集的情况.例如(2,3,5,4,2,3,3,2,5,4) 方法:先找出最大值最小值,之后统计每个数出现的次数,根据次数从小到大往数组里添加 计数排序法是一种不需要比 ...

  8. 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较

    2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...

  9. 《algorithms Unlocked》读书笔记3——计数排序

    <Algorithms Unlocked>是 <算法导论>的合著者之一 Thomas H. Cormen 写的一本算法基础,算是啃CLRS前的开胃菜和辅助教材.如果CLRS的厚 ...

随机推荐

  1. [洛谷P4592][TJOI2018]异或

    题目大意:有一棵$n$个点的树,第$i$个点权值为$w_i$,有两种操作: $1\;x\;y:$询问节点$x$的子树中与$y$异或结果的最大值 $2\;x\;y\;z:$询问路径$x$到$y$上点与$ ...

  2. [bzoj] 1068 压缩 || 区间dp

    原题 f[i][j][0/1]表示i-1处有一个M,i到j压缩后的长度,0/1表示i到j中有没有m. 初始为j-i+1 f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k ...

  3. kafka-zk-安装测试初体验

    第一步: 安装 安装工具brew install kafka 会自动安装依赖zookeeper 注:安装配置文件位置 /usr/local/etc/kafka|zookeeper 注: #tickTi ...

  4. shell运用

    在shell脚本一 中,我讨论了shell脚本的语法规范,shell脚本的变量,以及shell脚本的测试语句. 仅仅懂得这些只能写简单的脚本,在简单的脚本中各条语句按顺序执行,从而实现自动化的管理,顺 ...

  5. mysql的select的五子句

    转: http://www.cnblogs.com/billyu/p/5033167.html http://www.cnblogs.com/xiadong90-2015/p/4222965.html ...

  6. sudoers文件配置

    http://note.drx.tw/2008/01/linuxsudo.html foobar ALL=(ALL) ALL 現在讓我們來看一下那三個 ALL 到底是什麼意思.第一個 ALL 是指網路 ...

  7. udhcpd源码分析3--IP租赁管理

    1:重要的结构体 全局链表的成员struct dhcpOfferedAddr *leases 记录了当前租赁出去的IP信息 /* leases.h */ struct dhcpOfferedAddr ...

  8. linux-柔性数组

    柔性数组:在C99定义的结构体中,最后一个元素允许是未知大小(或者是0)的数组,它不占用结构体任何内存,这个数组叫做柔性数组,柔性数组前必须至少有一个其它成员. 使用方式: #include<s ...

  9. stout代码分析之六:Stopwatch

    在进行性能测试时,经常需要计算某个函数执行的时长.stout中的Stopwatch类可实现纳秒精度的计时. Stopwatch内部使用timespec记录开始和技术时间.   timeval和time ...

  10. RabbitMQ的使用总结

    RabbitMQ介绍 说明: Consumer (消费者):使用队列 Queue 从 Exchange 中获取消息的应用. Exchange (交换机):负责接收生产者的消息并把它转到到合适的队列. ...