桶排序像个桶,数据多而挤时间只有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(n≤999) 名候选人,每名候选人编号分别从 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<<" ";
}
}
}
最后总结
桶排序就是一把双刃剑,在关键时刻他可以使我们用不超时,但有时也会是内存爆炸,一定要谨慎使用。
下一篇将堆排序