神奇的桶排序
在学排序的时候,就想着有没有比O(logn)更快的排序的方法,在数据结构排序那章的时候学到快速排序的时候已经觉得没有更快的排序方法。自己写课设的时候,也就数据查询这方面的算法,就数据本身特性进行过改进,但是,始终无法突破O(logn)的限制,久而久之,也就认为没有更快的排序方法。
更不要说达到O(n)的量级。O(n)也就意味着存在与读取数据同样时间复杂度的排序方法。
举个例子,你读完数据时,还在等着sort()函数开始欢快的跑动时,然而还没开始就没结束了。你说激不激动。
不知道桶排时个人思路
学过的各种选择、归并、快排、插入、冒泡等排序,比较其共同点,都是读完数据后,在用尽各种方法,随着n的增加,让数据的有序度一步步提高。
for(int i=0;i<n;i++){
//所有已学排序都是针对这里的优化
//要想达到O(n)的量级,这里的操作不能有循环,
//也不能受数据规模影响
}
可能吗?达到O(n),当然,笔者只是一个认真听老师讲课的“乖学生”,但是还是想要挑战一下。就陷入了上面的死循环,用已学方法进行优化,发现不可能(当然,本人太菜,若真能做到,恳请相告。真得好奇)
切入正题(桶排序)
就在今天晚上,准备发奋学习,算法竞赛基础入门讲解时,发现了桶排序这个宝贝,醍醐灌顶,很是畅快。
应用条件:满足数据<=n,且n是读入数据量相对范围较大,越大越有神效。
例子
/*100000个数。
每个数都在100000以内
现在请把他们排成有序的
int T [10^5+5] ;
读入数据示例:7 4 5 3 2 2 1 5
T[i] 1 2 1 1 2 0 1 0
i 1 2 3 4 5 6 7 8
*/
for(int。i = 1;i <= n; ++ i){
int t;
cin >> t;
T[t]++;
}
对于像我一样,老师不教,自己就像不到这种排序方法的同胞们,那会了不亏;读的过程你的排序就完成了,很棒;
缺点
不可避免的存在缺点。
- 适用范围窄:只能用于数据分布密集且范围已知的情况;范围未知,数据分布分散时,你可以把数组开得很大。没必要,这就转到缺点二。
- (不满足适用条件下)占空间大,开那么大数组,太浪费了,满足适用条件的话,倒是省下不少空间。
- 只能对读入数据是整数起作用。当然将其余数据通过映射变成整形,可以,就是又要开个数组,空间复杂度增加。
最后,最快的桶排序代码就在上面(改成其他形式,适应变量类型增加映射等一切改进此排序算法的行为,都必定会劣化它的速度。)