开篇

最后更新于:2022-04-01 21:46:03

> 作者:Hawstein > 出处:[http://hawstein.com/posts/make-thiner-programming-pearls.html](http://www.hawstein.com/posts/make-thiner-programming-pearls.html) > 声明:本文采用以下协议进行授权: [自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0](http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh) ,转载请注明作者及出处。 ## 开篇 具体化你的解决的问题。下面是A和B的对话。 ~~~ A:我该如何对磁盘文件进行排序? B:需要排序的内容是什么?文件中有多少条记录?每个记录的格式是什么? A:该文件包含至多10,000,000个记录,每条记录都是一个7位整数。 B:如果文件那么小,为什么要使用磁盘排序呢?为什么不在主存中对它排序? A:该功能是某大型系统中的一部分,大概只能提供1MB主存给它。 B:你能将记录方面的内容说得更详细一些吗? A:每个记录是一个7位正整数,没有其它的关联数据,每个整数至多只能出现一次。 ... ... ~~~ 经过一系统的问题,我们可以将一个定义模糊不清的问题变得具体而清晰: ~~~ 输入: 所输入的是一个文件,至多包含n个正整数,每个正整数都要小于n,这里n=10^7。 如果输入时某一个整数出现了两次,就会产生一个致命的错误。 这些整数与其它任何数据都不关联。 输出: 以增序形式输出经过排序的整数列表。 约束: 大概有1MB的可用主存,但可用磁盘空间充足。运行时间至多允许几分钟, 10秒钟是最适宜的运行时间。 ~~~ 如果主存容量不是严苛地限制在1MB,比如说可以是1MB多,或是1~2MB之间, 那么我们就可以一次性将所有数据都加载到主存中,用Bitmap来做。 10,000,000个数就需要10,000,000位,也就是10,000,000b = 1.25MB。 程序可分为三个部分:第一,初始化所有的位为0;第二,读取文件中每个整数, 如果该整数对应的位已经为1,说明前面已经出现过这个整数,抛出异常,退出程序 (输入要求每个整数都只能出现一次)。否则,将相应的位置1;第三, 检查每个位,如果某个位是1,就写出相应的整数,从而创建已排序的输出文件。 如果主存容量严苛地限制在1MB,而使用Bitmap需要1.25MB, 因此无法一次载入完成排序。那么,我们可以将该文件分割成两个文件, 再分别用Bitmap处理。分割策略可以简单地把前一半的数据放到一个文件, 后一半的数据放到另一个文件,分别排序后再做归并。 也可以把文件中小于某个数(比如5,000,000)的整数放到一个文件,叫less.txt, 把其余的整数放到另一个文件,叫greater.txt。分别排序后, 把greater.txt的排序结果追加到less.txt的排序结果即可。
';