【Big data】外部排序

外部排序指要排序的数据大于内存空间的排序。是out-of-core算法。out-of-core算法的时间复杂度高度依赖IO次数,因为对内存的读取速度远远大于对disk的读取速度。所以内存中的处理时间可以不计,整个算法的复杂度由IO次数决定。IO的操作又是以block为基础的。

假设内存大小为M,block大小是B,排序数据是n。

第一种是2-路排序。

1.首先把数据分成n/M组,每一组调入内存一次,做一次排序,得到n/M组有序的数据。

2.对有序数据做2-路merge。过程大致是把所有的相邻的M大小的两块数据merge,然后是所有的2M大小的merge。。。直到n/2的merge。

最终会形成一个树状的结构,最底层的节点共有n/M个。因此2^(h - 1) = n/M,高度h=log(n/M) + 1。

IO次数:树中的每一层都是要遍历一次所有的数据,每一块都要进入一次内存,因此每一层的merge的IO次数是n/B,那么总的次数O((n/b) * log(n/M))。

下图是树状图:



那么如何进行一次merge操作呢?内存大小为M,所以每一个list只能拿进来M/2的数据,然后设置一个output块,大小为B,每选择的较小的数据就放入output块知道output满,满了以后就把output内的数据放回disk。同样在内存中的两个list的数据,一旦消耗了一块,也需要再从disk中拿入一块,这里就涉及了disk如何管理数据的问题,比如说每一次都是取disk后面那个list的数据,最终disk前面可能放不下merge以后的数据,需要一些数据后移才行。下面是一个例子:


第二种是k-路merge:

根据上述分析,一组相同大小的merge都需要n的数据进入内存一次,所有总共的IO次数正比于之前树的高度。要优化就要减少树的高度,就要增加数的factor即,度数。假设现在度数是k,那么要mergek个list,每一个list进入内存的大小为M/k,一定大于B,block是IO操作的最小单位,所以k最大是M/B.按照这个思路就可以求出最优的merge sort的IO次数。

树的高度,k^(h - 1) = n/M, h = log(n/M) / log(M/B),所以最终最优的IO次数是(n/B) * h。

这里的merge是k-路merge,因此需要引入priorityqueue来从k个list里面选择最小值。其余不变。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值