外部排序

当我们要排序的文件太大以至于内存无法一次性装下的时候,这时候我们可以使用外部排序,将数据在外部存储器和内存之间来回交换,以达到排序的目的

排序思想

一天晚上,徒弟正在呆呆地看着星星,师傅突然坐在了他的旁边。

师傅:徒弟啊,天上的星星那么多,不妨你给他们按大小排个序吧。

徒弟:哦,这个怎么排?

师傅:具体到我们的编程,就是给你2G的数据在硬盘上,但是你只有256M的内存可以使用,怎么排这2G的数据呢?

徒弟:这么小的内存,装不下数据啊,怎么排呢?

师傅:还记得分而治之的思想吗?我们可以采用这种思想把它排好序。

徒弟:具体怎么做呢?

首先我们可以将2G的数据分成8份,分别加载到内存中进行排序,在内存中的排序方法可以用内部排序如快排、希尔等,如下图:

在这里插入图片描述

这些已经排好序的数据块我们称之为顺串

在这里插入图片描述

然后我们可以将两个顺串通过内存合并成一个顺串(长度为原来的两倍),经过四次合并就完成了。

注意:合并操作几乎不需要内存,只需要读入两个元素,选择一个最大的(或最小的)输出,然后再读入,再选择

在这里插入图片描述

按照这个方法一直来回合并,一直合并到最终的一个顺串(有序),此时排序完成。

举个实际的例子吧:

为了简化,设待排数据为:80,92,12,97,13,34,18,98,27,57,40,74,内存一次可以装三个数据。

在这里插入图片描述
将数据分为四份:

在这里插入图片描述

然后将每份读入内存,排序后写入硬盘

在这里插入图片描述

然后两两合并

在这里插入图片描述

输出哪个元素,就在那个元素所在的顺串(或者叫组)再次读入元素

在这里插入图片描述

在这里插入图片描述

就这样,一直合并到两个顺串完,如果一个顺串先完,剩下另一个顺串,那么就将剩下的顺串直接拷贝到硬盘上。

按照这个方法,把合并后的顺串继续合并,直到最终合并成一个总的顺串,排序结束。

在这里插入图片描述

优化

徒弟:我听说硬盘的读写速度比内存要慢的多,按照这种排序那岂不是很慢。

师傅:好问题,一般我们会从两方面去优化。

对同一个文件而言,采取这种排序方法所需读写外存(磁盘)的次数与归并趟数有关,很容易理解,归并趟数越多,内存和外存的交互次数就越多。

假设初始时有 m 个顺串,每次对 k 个顺串进行归并,归并趟数就为:
在这里插入图片描述

比如我们的例子,刚开始的时候顺串(初始顺串)有 4 个(m=4),每次对 2 个顺串进行归并(k=2),那么归并趟数就为:
在这里插入图片描述

到此,我们优化的目标就很明确了:

① 增加归并的顺串数量 k

② 减少初始顺串的个数 m

优化方法:多路归并

之前是两两一合并,使得归并顺串的数量为 2(这叫2路归并), 我们可以多归并几个,这样我们就可以减少归并的趟数了,从而减少外存的读写次数

以刚才的例子来看,这次我们假设内存大小可以容纳四个元素,我们一次对4个顺串进行归并(4路归并)

在这里插入图片描述

这样只需要一次合并就可以了,外存读写次数为24(12读+12写),比之前的48少了一半,于此同时我们也可以看到需要更大的内存了,内存之中选出最大值也会更耗时,所以要权衡选 k。

在内存之中选最大(或最小)值时,可以选择一个元素与其他元素一个一个比,然后更新最值,但是效率会比较低,一般采取败者树来选择,在此就不展开说了,有兴趣的可以查阅相关资料。

转自:https://www.itcodemonkey.com/article/5578.html

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值