每天一点点之数据结构与算法 - 线性排序:桶排序(Bucket sort)
课前学习:
什么是线性排序 ?我们把时间复杂度是O(n)的排序算法叫作线性排序。因为这些排序算法的时间复杂度是线性的。
桶排序(Bucket sort)
核心思想就是将要排序的数据分到几个有序的桶里,每个桶里的数据在单独进行排序。
桶排序的时间复杂度为什么是O(n)呢?我们来分析一下。
如果需要排序的数据有n个,我们把它均匀的分布到m个桶内,那么每个桶就有k=n/m个。每个桶内使用快速排序,时间复杂度是O(k * logk)。m个桶的时间复杂度就是 O(m * k * logk),因为k=n/m,所以所有桶的时间复杂度就是O(n*log(n/m))。当桶的个数无限接近于数据个数n时,log(n/m)无限接近于一个小的常量,这个时候桶排序的时间复杂度接近于O(n)。
什么场景应该使用桶排序?
首先,要排序的数据很容易就能划分成m个桶,同时桶与桶之间也是有序的。
其次,数据在每个桶之间的分布是比较均匀的。
桶排序比较适合在外部排序中
比如说我们有10GB的订单数据,我们希望订单金额(正整数)进行排序,但是内存有限,没办法一次性将所有数据都加载到内存中。这个时候怎么办呢?
下面来说一下如何通过桶排序的处理思想来解决这个问题。
我们可以先扫描一遍文件,查看订单金额的数据范围。经过扫描我们得到最小1元,最大10万元。我们将所有订单根据金额划分到100个桶内,第一个桶存储1-1000元之间的订单,第二个桶存1001-2001元之间的订单,以此类推。并按照金额范围大小的顺序对桶进行命名(00,01,02...99)。
理想情况下,订单会均匀的分布在每一个桶中,我们就可以对每个桶进行单独快排。
不过,均匀分配是不现实对,可以看出,某一个桶内数据会特别多,数据没办法一次性读取。又该怎么办呢?
其实,针对这种划分之后还是比较大对桶,还可以继续划分,比如,订单在1元到1000元之间的比较多,我们可以将这个桶继续划分为10个小桶。如果划分之后桶内数据还是比较多,还可以继续划分,以此类推,直到所有文件都可以读入内存为止。
来源于王争老师的数据结构与算法之美