为什么要写这样滴一篇博客捏...因为一个新初一问了一道水题,结果就莫名其妙引起了战斗。

然后突然发现之前理解的桶排序并不是真正的桶排序,所以写一篇来区别下这三个十分相似的排序辣。

老年菜兔的觉醒!!!

记数排序

记数排序是一种很快的排序算法,但是要很多的空间。

具体的操作:

比如说给一个这样的数列:    6 9 3 2 3 5

我萌需要一个数组   a[i] 表示 数列中 数值为 i 的有多少个

这样 就可以 O(n) 处理出这个数组

  read(x);
a[x]++;

比如辣个栗子的a数组是这样滴

i 1 2 3 4 5 6 7 8 9
a[i] 0 1 2 0 1 1 0 0 1

然后这个数组有什么用捏

可以发现,只需要枚举 i (如栗子里是 1≤i≤9  )

然后输出 a[i] 个 i 后就是一个从小到大排序后的数列

for i= to  do (通常可以取数列中的最大数max,这里取栗子的9)
for j= to a[i] do
write(i,' ');

这样之后就会输出   2 3 3 5 6 9

这就是记数排序(老年菜兔之前把计数排序误以为是桶排序QAQ)

效率基本为 O(N) 但是有一个缺陷,就是当数列的值十分十分大的时候,数组就开不下了。

这个问题怎么解决好捏,就是桶排序和基数排序辣!

桶排序

桶排序实际上是对计数排序的一些优化,他把时间又换回了一部分空间(计数排序用空间换时间)。

桶排序思想是什么捏?

继续举个栗子呀  6 9 3 2 3 5 (咦好熟悉)

首先我萌要定一个值 m 这个值可以任意定,但会影响到效率。

m是干什么用的?

不如这样理解一下,计数排序实际上就是用了好多好多个桶 总共 max 个

而桶排序是用了 (max/m) 个桶 所以这个 m 的含义实际上是区间范围。

计数排序是桶排序的一种特殊情况,就是 取 m=1的时候。

这时我萌需要一个数组 a[i,j]表示 第 i 个桶中的第j个元素的数值。

(通常不用数组而是链表,原因是可能有这样的数据 如数列中全都是1-3范围的 这时数组就开不下,如果n十分大)

嗯列个表吧

这里我萌取 m=3 (就是举个栗子)

桶中数据的范围 1~3 4~6 7~9
相应的i(也就是第几个桶) 1 2 3
桶内的元素 3,2,3 6,5 9

这时发现什么捏...每一个桶里的元素是无序的。

所以对每一个桶都做一个其他的排序,如快排。

然后排序后再把这些桶合并起来就好啦

诶???每一个桶?辣么效率岂不是很低。

答案是否定的,相反,桶排序效率通常比快排快。

快排的平均效率为O(n log n) 而桶排捏是 O(max/m *m log m) 即 O(max log M) 假设max=n=1000000(1百万)

快排的计算量约 23000000(2300万) 而 桶排序如果取M=2500(既省了一点空间,又有很高的时间效率) 的计算量约 12000000(1200万)

可见桶排序效率也比较高。

而且桶排序每个桶的排序算法还可以换为其他的不一定要快排。

桶排序的应用似乎不多,而似乎很多人搞混了基数排序与桶排序。

相比之下把基数排序误认为是桶排序的人会更多的样子。

所以基数排序的应用应该更广。

基数排序

基数排序的方法更是神奇,他用到了计数排序的思想。

基数排序的操作我还是要举个栗子...不过图就不放了QAQ不然水的成分有点大

如:543 123 756 666 841 322 10 799 69 (终于换了个栗子,因为上一次栗子次掉了)

基数排序的操作是这样的。

最低位(个位)为一个关键字,次低位是一个关键字...以此类推。

我萌先对最低位为关键字做一次计数排序。

如果依旧用桶来比喻的话,因为一个位数上只会有0-9 这些数字。

所以就是10个桶

列个表吧

0 1 2 3 4 5 6 7 8 9

第1次操作后

桶里的元素

10 841 322 543,123     756,666     799,69

然后第一次操作后再合并起来就是这样的数列 (注意每一个桶内是无序的,都是按原来数列的位置)

10 841 322 543 123 756 666 799 69

还是一个无序的数列,接着对次低位为关键字做记数排序

0 1 2 3 4 5 6 7 8 9

第2次操作后

桶里的元素

  10 322,123    841,543 756  666,69     799

然后第二次操作后再合并起来就是这样的数列(注意每一个桶内依旧是无序的,都是按第一次操作后的数列的位置)

10 322 123 841 543 756 666 69 799

然后就第三低位为关键字做记数排序

0 1 2 3 4 5 6 7 8 9

第2次操作后

桶里的元素

 010,069 123    322    543 666  756,799  841  

然后合并

10 69 123 322 543 666 756 799 841

这时排序结束,数列有序了。

是不是很神奇捏?

为什么要对每一位都做一次计数排序?

实际上就是改变位置。比如如果出现了 123 124 这样的元素,在原来数列是这样的 124 123

辣么对最低位进行计数排序就可以变成 123 124 从而改变了位置。

好了,辣基数排序的效率?

设最大值有 d 位

约O(d*n) 的效率

而d是十分小的,相比桶排序,虽然效率变低了一点,但适用于一些数值十分大的数据。

再扩充一点基排

实际上,这里使用了10个桶,辣么可不可以多用些桶捏?当然可以

我萌可以使用100个桶,将最低位和次低位看成一个整体 为一个关键字,比如 5678 此时 以78 为一个关键字 56为另一个关键字。

然后操作是一样的但是却只有 d/2个关键字了,从而效率又快了,但空间变多了,变成了100个桶。

以此类推,还有1000 10000 ...个桶。辣如果不是整10个桶行不行,当然行,这样的话需要把10进制数看为其他进制的数来做计数排序。具体就不细讲啦~

好啦~讲完啦,总结一下吧,总体来说,三个排序都是用到了计数排序的思想。

桶排序效率高,但数值过大还是无法使用,而基数排序不仅效率高了很多,而且适用数值大的数据。

老年菜兔的讲解结束啦~撒花~

记数排序 & 桶排序 & 基数排序的更多相关文章

  1. Python线性时间排序——桶排序、基数排序与计数排序

    1. 桶排序 1.1 范围为1-M的桶排序 如果有一个数组A,包含N个整数,值从1到M,我们可以得到一种非常快速的排序,桶排序(bucket sort).留置一个数组S,里面含有M个桶,初始化为0.然 ...

  2. python 排序 桶排序

    算法思想: 桶排序将数组分到有限数量的桶里.然后每个桶里再分别排序(使用任何算法) 当要倍排序的数组内的数值时均匀分配的时候,桶排序使用线性时间O(n) 步骤: 根据最大值.最小值.桶内数据范围设定一 ...

  3. 排序基础之非比较的计数排序、桶排序、基数排序(Java实现)

    转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/6639353.html  比较和非比较排序 快速排序.归并排序.堆排序.冒泡排序等比较排序,每个数都必须和其他 ...

  4. 桶排序与基数排序代码(JAVA)

      桶排序 publicstaticvoid bucketSort(int[] a,int max){         int[] buckets;           if(a==null || m ...

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

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

  6. 桶排序和计数排序的理解实现和比较(Java)

    比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比较排序.在排序的最终结果里,元素之间的次序依赖于它们之间的比较.每个数都必须和其他数进行比较,才能确定自己的位置.比较排序的优势是 ...

  7. 计数排序与桶排序python实现

    计数排序与桶排序python实现 计数排序 计数排序原理: 找到给定序列的最小值与最大值 创建一个长度为最大值-最小值+1的数组,初始化都为0 然后遍历原序列,并为数组中索引为当前值-最小值的值+1 ...

  8. [C++] 习题 2.14 用队列实现桶排序

    目录 前置技能 队列(已在上篇提到栈的时候顺便提到了,不再赘述) 桶排序 具体实现 由用户输入n个10以内的数,每输入i(0≤i≤9),就把它插入第i号队列中,最后把10个队列中的非空队列,按队列号从 ...

  9. 线性时间的排序算法--桶排序(以leetcode164. Maximum Gap为例讲解)

    前言 在比较排序的算法中,快速排序的性能最佳,时间复杂度是O(N*logN).因此,在使用比较排序时,时间复杂度的下限就是O(N*logN).而桶排序的时间复杂度是O(N+C),因为它的实现并不是基于 ...

随机推荐

  1. Load Balancing with NGINX 负载均衡算法

    Using nginx as HTTP load balancer Using nginx as HTTP load balancer http://nginx.org/en/docs/http/lo ...

  2. 让网站全面支持v4/v6 HTTP、HTTPS、HTTP/2最简单方法是增加Nginx反向代理服务器

    bg6cq/nginx-install: nginx install script https://github.com/bg6cq/nginx-install [原创]step-by-step in ...

  3. chrome 因js死循环卡住

    chrome因js死循环卡住的解决方法: top命令查看chrome的pid kill -9 pid 杀死整个chrome进程(所有网页都关闭)

  4. python看内存

    打断点,跑起来 ps -ef | grep python 找到PID(两个数的第一列) cat  /proc/PID/status 内存主要看四个字段: vmpeak 虚拟内存历史峰值 vmsize ...

  5. rest_framework 之版本控制

    一 作用 用于版本的控制 二 内置的版本控制类 from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderV ...

  6. yarn的使用

    yarn 的安装 npm install -g yarn yarn -version  查看yarn是否安装成功 一.首先需要了解的命令 npm install === yarn —— install ...

  7. Linux df命令

    df命令用于查看磁盘的分区,磁盘已使用的空间,剩余的空间 1.用法 df [选项] [文件..] 2.命令选项 -a,--all 全部文件系统-h,--human-readable 以以合适的单位来显 ...

  8. Linux cal命令

    cal命令时查看日历的相关命令 1.用法 cal [选项] [[[日] 月] 年] 2.命令选项 -1, --one 只显示当前月份(默认) -3, --three  显示上个月.当月和下个月 -s, ...

  9. JS生成随机字符串的多种方法

    这篇文章主要介绍了JS生成随机字符串的方法,需要的朋友可以参考下 下面的一段代码,整理电脑时,记录备查. <script language="javascript"> ...

  10. PAT 1125 Chain the Ropes[一般]

    1125 Chain the Ropes (25 分) Given some segments of rope, you are supposed to chain them into one rop ...