外部排序

如何排序10G个元素

我们内存没有这么大,我们没办法放进大数组里面

有一部分放在数组里面,有一部分放在外面,就是硬盘或者网络上其他节点,

就是所谓的外部排序


扩展的归并排序

我们数据不要分左右两端,我们分很多段


每一段给一个节点进行排序,每一段他的数据量我们可以控制小到放在内存里可以放得下

那这个节点就可以做普通的排序,快速归并

拍出来之后每个节点都是有序序列,每个有序序列都归并节点


我们把大数据且分到每一个节点上,每一个节点做一个内部排序然后进行节点归并

如何实现?

首先切分很简单,500M1G看看有多大

切分玩之后节点内部排序这个很简单,放在一个数组里调用库函数就拍出来了

因此整个算法的关键就在归并节点的实现


k路归并,我们发现我们有很多串有序数据传过来

2,1,3,4从上到下分别是从上到下,2,1,3,4如何选取最小的数

k路要比较k次

我们要运用堆的数据结构


堆是一棵树,是一个完全二叉树(从上到下,从左到右都是铺满的)

树根1拿掉就是2,2就是树根,2拿到就是2的左子树根

堆里面找最小元素只要logn

我们不需要实现是PriorityQueue

实际上是优先队列



一个个push进去,pop出来就是最小的1,后面2,3,4

首先一上来先把2,1,3,4push进去

然后不断的pop,pop一个元素补一个元素,当我们做完之后我们就做完了,每次pop补一个都是log运算量

那我们归并节点这样做就完成了吗?

还有一个思考的地方


我们任然是10G的数据

我们归并节点的数据还是不够

这些数据不能全放在内存里,归并节点到底要放多少数据在内存里呢    

我们只要把每个数据源的最小放在内存里就可以了

我们只要把每个数据源最小的元素,我们只要把2134放在内存里

把1拿掉我们要把后面的读出来,

数据源是硬盘建,也可能是网络传输

我们这个读取查询过程会很慢,效率很低

因此我们通常做法是防缓存

我们从每个数据源读取他最小的一批数据放在内存里面,我们这例子里面放在


这样我们就好做了,我们把1拿出来,我么吧2,3拿出来

我们发现归并节点非常复杂

这个归并程序编写是很复杂

就要使用Iterable<T>接口

可以不断获得元素的能力

他是一个接口没有实现,元素存储/获取方式被抽象,与归并节点无关

 不需要考虑元素怎么存储怎么获取

Iterable<T> merge(List<Iterable<T>> sortedData);

会变成这样,一串Iterable<T>

这就是被各节点被分别拍完序的数据

但是第一个一个元素还是一组一组输出的,这个不是merge考虑的

merge是负责出Iterable<T>

他可以考虑,我们是不是可以缓存多少以后一口气输出到文件


架在内存和网络文件的层次结构上面的,

归并数据源来自Iterable<T>.next()

我们归并节点怎么做呢,我们一上来先从每一个数据源调用最小的源,然后加到prorityto里面去

接下俩从prorityto pop元素,找到pop的数据源,获得下一个元素,下一个元素是怎么来的?

如果换冲区空那么读取下一批元素放入缓冲区,

给出换出区还没被输出的最小元素

这样有什么好处?

首先我们只需要对每个数据调用next

数据源自己他很灵活

可配置项:缓冲区大小,如何读取下一个元素

缓冲区大小不知道我们很难确定我们可以给他5K,10K或者1M两M都可以

如何读取下一批也可以配置的

下一个元素可能在文件没可能在网络

读文件和读网络都是读,这样一来我们归并函数只要写一遍,以后又可以用在文件上又可以用在网络上

这就是我们外部排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值