桶排序(Bucket Sort)有时也称为盒子排序(Bin Sort),来源于邮局使用的盒子信件分发方法。桶排序的有效性需假定输入数据是由一个完全随机过程产生,即要求桶排序的输入数据呈均匀分布,例如,输入数据随机均匀分布在区间[0,
1)。
桶排序思想如下:
1)把区间[0, 1)分解为n个大小相等的桶;
2)将n个输入数据按照其取值不同分配到n个桶里面;
3)对每个桶里面的数据进行排序;
4)然后将桶里面的数据按顺序收集。
桶排序的伪代码程序如下:
输入数组:[1..n],对任意i,我们有0≤A[i]<1
辅助数组:B[0..n-1]个链表,初始状态均为空
BUCKET-SORT(A, n):
For i=1 to n do
将数据A[i]插入链表B[floor(n×A[i])]里
For i=0 to n-1 do
对链表B[i]里面的数据进行插入排序
将链表B[0]、B[1]、...、B[n-1]首尾相连链接起来
注意:上面对每个桶里面的元素使用平方级的插入排序算法,一个原因是在我们假定输入元素是均匀分布后,分配到任意一个特定桶里面的元素个数不会太多(否则就不均匀了,发生了聚集),因此插入排序的复杂性可以不用计较。
通过分析可以知道,桶排序是一个线性排序算法。
==============转载的分割线===============
=====http://hxraid.javaeye.com/blog/649831#comments=====
(有修改)
桶排序在海量数据中的应用
一年的全国高考考生人数为500
万,分数使用标准分,最低100 ,最高900
,没有小数,你把这500 万元素的数组排个序。
分析:对500W数据排序,如果基于比较的先进排序,平均比较次数为O(5000000*log5000000)≈1.112亿。但是我们发现,这些数据都有特殊的条件:
100=<score<=900。那么我们就可以考虑桶排序这样一个“投机取巧”的办法、让其在毫秒级别就完成500万排序。
方法:创建801(900-100)个桶。将每个考生的分数丢进f(score)=score-100的桶中。这个过程从头到尾遍历一遍数据只需要500W次。然后根据桶号大小依次将桶中数值输出,即可以得到一个有序的序列。而且可以很容易的得到100分有***人,501分有***人。
实际上,桶排序对数据的条件有特殊要求,如果上面的分数不是从100-900,而是从0-2亿,那么分配2亿个桶显然是不可能的。所以桶排序有其局限性,适合元素值集合并不大的情况。
题目:在一个文件中有 10G
个整数,乱序排列,要求找出中位数。内存限制为 2G。只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存)。
关于中位数:数据排序后,位置在最中间的数值。即将数据分成两部分,一部分大于该数值,一部分小于该数值。中位数的位置:当样本数为奇数时,中位数=(N+1)/2
; 当样本数为偶数时,中位数为N/2与1+N/2的均值(那么10G个数的中位数,就第5G大的数与第5G+1大的数的均值了)。
分析:
既然要找中位数,很简单就是排序的想法。那么基于字节的桶排序是一个可行的方法。
思想:将整型的每1byte作为一个关键字,也就是说一个整形可以拆成4个keys,而且最高位的keys越大,整数越大。如果高位keys相同,则比较次高位的keys。整个比较过程类似于字符串的字典序。
第一步:把10G整数每2G读入一次内存,然后一次遍历这536,870,912即(1024*1024*1024)*2
/4个数据。每个数据用位运算">>"取出最高8位(31-24)。这8bits(0-255)最多表示255个桶,那么可以根据8bit的值来确定丢入第几个桶。最后把每个桶写入一个磁盘文件中,同时在内存中统计每个桶内数据的数量,自然这个数量只需要255个整形空间即可。
代价:(1) 10G数据依次读入内存的IO代价(这个是无法避免的,CPU不能直接在磁盘上运算)。(2)在内存中遍历536,870,912个数据,这是一个O(n)的线性时间复杂度。(3)把255个桶写会到255个磁盘文件空间中,这个代价是额外的,也就是多付出一倍的10G数据转移的时间。
第三步:继续以内存中的整数的次高8bit进行桶排序(23-16)。过程和第一步相同,也是255个桶。
第四步:一直下去,直到最低字节(7-0bit)的桶排序结束。我相信这个时候完全可以在内存中使用一次快排就可以了。
代价:(1)循环计算255个桶中的数据量累加,需要O(M)的代价,其中m<255。(2)读入一个大概80M左右文件大小的IO代价。
注意,变态的情况下,这个需要读入的第128号文件仍然大于2G,那么整个读入仍然可以按照第一步分批来进行读取。第二步:根据内存中255个桶内的数量,计算中位数在第几个桶中。很显然,2,684,354,560个数中位数是第1,342,177,280个。假设前127个桶的数据量相加,发现少于1,342,177,280,把第128个桶数据量加上,大于1,342,177,280。说明,中位数必在磁盘的第128个桶中。而且在这个桶的第1,342,177,280-N(0-127)个数位上。N(0-127)表示前127个桶的数据量之和。然后把第128个文件中的整数读入内存。(平均而言,每个文件的大小估计在10G/128=80M左右,当然也不一定,但是超过2G的可能性很小)。
整个过程的时间复杂度在O(n)的线性级别上(没有任何循环嵌套)。但主要时间消耗在第一步的第二次内存-磁盘数据交换上,即10G数据分255个文件写回磁盘上。一般而言,如果第二步过后,内存可以容纳下存在中位数的某一个文件的话,直接快排就可以了。
分享到:
相关推荐
下面我们将详细讨论桶排序的时间复杂度计算公式及其推导过程。 首先,我们假设数据均匀且独立地分布在一个[0, 1)的区间内,桶的数量为k,每个桶内部采用线性排序(如插入排序)。在最理想的情况下,每个桶内元素...
Hive是一种数据仓库软件项目,用于对存储在分布式存储系统(如Hadoop)中的大数据进行查询和管理。它定义了一种类似于SQL的查询语言,称为HiveQL,允许用户执行数据查询、数据摘要和数据挖掘等操作。...
- **内存限制**:桶排序需要额外的存储空间来保存桶及其内容,因此需要考虑系统的内存限制。 综上所述,Erlang的百万级用户排行榜桶排序方案是通过充分利用Erlang的并发优势和桶排序的特性,有效地处理大规模数据的...
### Java实现桶排序算法 #### 实现原理与关键步骤 桶排序是一种高效的排序算法,尤其适合于处理数据分布均匀的情况。其核心思想是通过将数据分成若干个“桶”,然后分别对这些桶内的数据进行排序,最后将这些排序...
桶排序和快速排序是两种不同的排序算法,它们在不同的场景下有着各自的效率优势。本文将介绍如何在Python中结合这两种算法...理解并掌握这两种排序算法及其结合应用,对于编写更高效、适应性强的排序代码具有重要意义。
它将数组分到有限数量的桶里,每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序),最后把各个桶的数据串接起来。 #### 示例代码分析 **升序** ```cpp #include using namespace...
常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序、希尔排序、桶排序、计数排序和基数排序等。这些算法在时间复杂度、空间复杂度和稳定性等方面各有不同,适用于不同的数据场景。例如,...
排序算法有很多种,如冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序、希尔排序、计数排序、桶排序、基数排序等。每种排序算法都有其独特的优缺点,适用的场景也不同。例如: 1. 冒泡排序:简单直观,...
本文将探讨线性排序算法,包括桶排序、计数排序和基数排序,并通过一个具体的案例——根据年龄对100万用户数据进行排序,来深入理解这些算法的工作原理及其适用场景。 #### 二、线性排序算法介绍 线性排序算法是一...
本文将深入探讨两种常见的分配排序方法:桶排序(bucket sort)与基数排序(radix sort),并通过Python代码实例来解析这两种排序算法的工作原理及其应用技巧。 #### 一、桶排序(Bucket Sort) **定义与原理** 桶排序...
基数排序适用于数值范围较小且位数确定的情况,计数排序适用于数值范围较小且连续的情况,桶排序则将数据分配到多个桶中再进行排序,桶越多效率越高,但空间需求也越大。 在选择排序算法时,应考虑以下因素: - ...
本资源"各种排序算法Demo"提供了一系列用Java语言实现的排序算法示例,旨在帮助学习者理解和掌握这些算法的工作原理及其应用。以下是这些排序算法的详细介绍: 1. 直接插入排序(直接插入法): 直接插入排序是一...
以下是C++中四种经典的排序算法:快速排序、冒泡排序、桶排序和归并排序,它们都有各自的适用场景和优势。 一、快速排序 快速排序是一种高效的排序算法,由英国计算机科学家C.A.R. Hoare在1960年提出。它的基本思想...
- **非比较性排序**:这一类排序算法不需要通过元素之间的比较来决定它们的顺序,而是利用数据本身的特性进行排序,例如计数排序、桶排序等。 此外,根据排序后相同元素的相对位置是否保持不变,还可以将排序算法...
桶排序将元素分配到有限数量的桶里,每个桶再单独排序,最后把所有桶的元素按顺序合并。适合于近似均匀分布的数据,时间复杂度可达到线性O(n + k)。 9. 基数排序(Radix Sort) 基数排序是根据数字的位数从低到高...
- **原理**: 桶排序是排序算法中的一种,其基本思想是将数组分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序),然后再把桶里的数据汇集起来组成排序后的...
例如,计数排序适用于整数排序,桶排序适用于元素均匀分布的情况,基数排序则按照每个数字位进行排序,适用于整数排序且位数较少的情况。 以上就是一些基本的排序算法,每种都有其适用的场景和优缺点。实际应用中,...
下面我们将深入探讨这些排序算法的核心概念及其应用。 1. 冒泡排序(Bubble Sort) 冒泡排序是一种简单直观的排序算法,通过不断交换相邻的未排序元素来逐步将最大或最小的元素“冒”到数组的一端。虽然效率较低,...
8. 桶排序(Bucket Sort):当输入数据均匀分布于一定区间时,桶排序性能优秀。将数据分到多个桶里,每个桶内部排序,最后按顺序依次取出。时间复杂度可以达到线性O(n),但依赖于数据分布。 9. 基数排序(Radix ...
桶排序将数据分布到多个“桶”中,每个桶内部再单独进行排序,最后将所有桶的元素依次合并。C语言实现需要处理桶的创建、元素分配和合并。当输入数据均匀分布时,桶排序可以达到线性时间复杂度O(n + k)。 10. 基数...