版权声明:本文为 DouMiaoO_Oo 原创文章,未经允许不得转载!
本章提出一个问题,电话号码有10位,前3位是固定区号800 ,后面还有7位数字,需要对这些电话号码进行排序。即:
输入: 一个最多包含n个正整数的文件,每个数都小于 $ n $ ,其中 $n =10^7 $。如果在输入文件中有任何整数重复出现就是致命错误。没有其他数据与该整数相关联。
输出:按升序排列的输入整数的列表
约束:最多有(大约)1 MB的内存空间可用,有充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要进一步优化了。
从这里我们可出,记录中只有正整数。约束条件是业务需求导致的。这里作者一步步提出了三种方法:
归并排序,即磁盘中的外部排序,读取一遍输入文件,但是需要多次读写工作文件(中间文件)多趟排序,因为1MB能保存 25 K 25K 25K 个数据,所以 1 0 7 10 ^ 7 107 个 ∈ [ 0 , 1 0 7 ] \in [0, 10 ^ 7] ∈[0,107] 的数可以划分为40个区间,可以通过多次读取输入文件来排序。对于第 i i i 趟读取输入文件,我们可以排序大小在 [ 25 K ∗ ( i − 1 ) , 25 K ∗ i ) [ 25K * (i-1), 25K * i ) [25K∗(i−1),25K∗i) 区间内的数。位图或者位向量(bit vector/bit map) 来做。在我目前看来,我觉得位向量和 桶排序(bucket sort)很类似,这里先记录一下。位向量就是一组bit构成的基本数据结构。 我们把可以用的1MB的内存利用二进制展开,这样能够得到的bit数目有 1024*1024*8 = 8,388,608。位向量就是指,从左往右看对于第i 个比特,如果这一位是1,则代表存在i这个数。举例来说:
给定一个byte,也就是8个bit。如果某组整数可以通过位图表示为 01010000,此时从左往右第5个和7个bit是1,所以这个位向量代表就是{5, 7} 这样一个集合。
书中通过额外提供了部分内存,得到 1 0 7 10^7 107 个bit的内存(大约1.25MB),所以此时利用位向量可以在内存中保存全部的输入数据。
版权声明:本文为 DouMiaoO_Oo 原创文章,未经博主允许不得转载!
编程珠玑 第二版 修订版