怎样给一个磁盘文件排序?

最近看到这个问题,抽时间看了一下。

编程珠玑里面,对于这个问题有很详尽的描述,这里我将读后感发出来与大家共享。

众所周知,磁盘文件往往很大,而内存很小,在给磁盘文件的排序过程中,磁盘访问时间远远大于内存里面的排序时间,想要快速将磁盘文件排序输出,就要尽量的避免多次访问磁盘。

常规的做法是基于磁盘的归并排序,其思想十分简单:一次性读入输入文件,在内存中进行归并排序,期间需要多次访问工作文件,最后输出文件一次。这种做法使得程序需要频繁的访问磁盘工作文件,磁盘的存取速度大大的拖延了程序的运行时间,性能比较低下。

为了尽量减少磁盘的访问次数,出现了一种新的做法:根据内存大小大致将磁盘文件分成有限的n等份(分的时候需要确定数据范围,例如第一份包含0-999的任何存在的数字,第二份包含1000-1999的任何存在数字......),每次将一份数据读入内存进行排序,最后输出。在这种情况下,由于不再使用中间文件,程序只需要访问磁盘n+1次即可完成全部排序,在时间和空间上都比第一种有所优化。

那么以上问题引发了以下思考,是否存在一种方法,只需读取和输出磁盘文件各一次,就能完成全部排序?

位图法可以解决这个问题。

以上受限于内存空间大小,我们无法一次读入所有数据进行处理。但是如果我们把每一个位(bit)都表示一个数,这个问题就能得到大大缓解。

比如我们把一个连续空间的第8位置1表示文件中存在数字8,置0表示不存在数字8,那么100MB的空间就能存储100*(2^20)*8个数。

那么问题来了,当我输入一个数字i的时候,我们怎么把它存在第i位呢;当我知道第i为1的时候,我们怎么转化为数字i输出呢;这就要先明白什么是位向量

位向量:由一些二进制位组成的向量,用来存储一个数

示例:

对于32位的int类型 a[0]表示第1-32个数:0-31

a[1]表示第33-64个数:32-63

例如:数据i=31  对应位向量:  i/32=0  表示在a[0]单元上

                                                        i%32=31  表示在a[0]的第31位上.1<<(i%32

对应程序为:a[i/32]=a[i/32]|(1<<(i%32))

改用位运算:a[i>>5] |=  (1<<(i & 0x1F))

这里是一个可运行实例:


怎样给一个磁盘文件排序?_第1张图片

这样,磁盘排序的性能就比前2种方法大大提升了。

水平所限,难免有错,欢迎交流。

你可能感兴趣的:(怎样给一个磁盘文件排序?)