十大排序之——桶排序,双刃剑

桶排序像个桶,数据多而挤时间只有O(n),数据少而杂空间会爆,一般适用于统计票数等问题


提到十大排序,相信大家非常熟悉不过了,相信·大家在做排序题的时候第一时间想到的肯定是冒泡排序,选择排序等,但是,我们今天要介绍的是——桶排序

优势——好神奇的思路

桶排序的特点莫过于思维灵敏,时间复杂度低,其甚至省掉了比较过程,那很多读者就会问了,那么他是怎样实现的呢,其实它的内部用一个数组存储了已经比较过的元素,当他碰见i的时候,他不会像普通排序这样直接线性扫描每一个元素,然后挤出一个位置来,这样的话,就算用链表存时间复杂度最坏也高达平方,更别说用数组了。
那桶排序是怎么进行存储的呢?首先,他把a[i]+1,然后再依次输出,当前位置加了几,他就输出几,怎么样,细细品味一下,是不是很巧妙呢,实际上这就照应了他你名字——桶。

劣势——别一来就迷上了

桶排序既然没有那么的被大家所熟知,肯定有他的原因,那就是,空间复杂度——下限低,上限高,你通过上面的分析,你会发现,当元素的大小相对密集,甚至有很多同样的元素时,使用桶排序就会非常的高效,那如果数据很散呢?比如下面这组数据:
1 2 3 3443454545 2376238 2937923874983649 38 29 39999 9923 -123
你会发现他的元素不多,只有不到十个,那么如果你用桶排序的话,你就会发现,数组会开到2937923874983649 + 123,你会发现就计算这个,你也许就要用高精度了,而这时,你就应该选择冒泡或选择排序,你会发现,就算是平方的复杂度,可能还没有2937923874983649 + 123慢。
所以我们总结一下:

用桶排序要慎重,不要动不动就用,数据太杂会爆炸,当数据都很紧时,你就可以用桶排序了,因为一个数组一个桶,在这个情况下就可以处理多个数据,复杂度就会降到线性O(n)

洛谷【选举学生会】

【深基9.例1】选举学生会

题目描述

学校正在选举学生会成员,有 n ( n ≤ 999 ) n(n\le 999) n(n999) 名候选人,每名候选人编号分别从 1 到 n n n,现在收集到了 m ( m < = 2000000 ) m(m<=2000000) m(m<=2000000) 张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。

输入格式

输入 n n n m m m 以及 m m m 个选票上的数字。

输出格式

求出排序后的选票编号。

样例 #1

样例输入 #1

5 10
2 5 2 2 5 2 2 2 1 2

样例输出 #1

1 2 2 2 2 2 2 2 5 5

分析

这道题我们会发现,他的数据有一个特点也就是多而密,这种情况下用桶排序再适合不过了,这时我们只需要用一层循环记录数据再用一层循环输出即可。下面给出代码:

#include<bits/stdc++.h>
using namespace std;
int n,x,a[2000002],m,i,j;
int main(){
 	ios::sync_with_stdio(false);
	cin>>m>>n;
	for(i=1;i<=n;i++){
		cin>>x;
		a[x]++;//记录x出现了多少次 
	} 
	for(i=1;i<=m;i++){
		for(j=1;j<=a[i];j++){//若a[i]=0,则不输出
			//a[i]用来计数,输出a[i]次i; 
			cout<<i<<" "; 
		}
	}
} 

最后总结

桶排序就是一把双刃剑,在关键时刻他可以使我们用不超时,但有时也会是内存爆炸,一定要谨慎使用。
下一篇将堆排序

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来自八中的小鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值