0%

编程珠玑第一章:磁盘排序问题

问题描述

输入:一个最多包含n个不同正整数的文件,每个数都小于n,其中n=$10^7$。

输出:将输入的整数按升序排序。
约束:最多有(大约)1MB的内存空间可用,有充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化了。

程序设计

如果每个号码使用7个字节存储(类似于char[]),那么1MB能存储 1 x 1024 x 1024 / 7 = 149796 个号码;
如果每个号码使用32位整数来表示的话(类似于Integer),在1MB的存储空间可以存储 1 x 1024 x 1024 / (32 / 8) = 262144个号码。
注:这里得出的两个最大存储号码个数与原书中不同,可能是书中使用了一种快速估算方法,为了方便后续计算,后面也使用1MB最多能存储250000个号码这个设定。

第一种方案,磁盘归并排序:
第二种方案,遍历输入文件40趟:

遍历输入文件,把0至249999之间的数都读到内存,排序,然后写入到第一个输出文件中;
遍历输入文件,把250000至499999之间的数都读到内存,排序,然后写入到第二个输出文件中;

依此类推,到第40趟遍历的时候对9750000至9999999之间的整数进行排序,这样就得到了40个从小到大排好序的文件了。
在整个排序过程中,内存排序非常高效,耗时的地方在40次的读取输入文件和输出排序后的号码到新文件。
疑问:为啥书里说这种排序仅写文件一次,而且不使用中间文件?追加写入也需要把源文件读到内存吧?1MB咋装得下?