编程珠玑学习笔记(1):简单磁盘文件数据排序

来源:互联网 发布:温庭筠入骨相思知不知 编辑:程序博客网 时间:2024/05/22 04:46

问题描述:

输入:一个最多包含n个正整数的文件,每个数都小于n,其中n=10**7。如果在输入文件中有任何整数重复出现就是致命错误。没有其他数据与该整数相关联。

输出:按升序排列的输入整数的列表。

约束:最多有(大约)1MB的内存空间可用,用充足的磁盘存储空间可用。运行时间最多几分钟,运行时间为10秒就不需要优化了。


算法思想: 用位图或者位向量表示集合。

例如可以用一个20位长的字符串来表示一个所有元素都小于20的简单非负整数集合。可以用如下字符串表示集合{1,2,3,5,8,13};

0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0

在上述问题中,7位十进制整数表示一个小于1000万的整数,可以使用一个具有1000万个位的字符串来表示这个文件,其中,当且仅当整数i在文件中存在时,第i位为1.


位图法

//伪代码

//初始化集合

for i = [0,n)

bit[i] =0

//将出现的元素插入到集合中

for each i in the input file

//输入排序了的元素

for i = [0,n)

if bit[i] == 1

       write i on the out put file


位向量法

#define BITSPEWORD 32

#define SHIFT 5

#define MASK 0x1F

#define N 10000000

int  a[1+(N-1)/BITSPEWORD]

//书中为a[1+N/BITSPEWORD] 当N能被BITSPEWORD整除时,会浪费1个int的空间

//不被整除时,最多是最后一个int的空间没有被完全利用而已

void set (int i)

{

// i >> SHIFT 将 i 定位到哪一个 int 中去 实际上等于 i / 32

// i & MASK 只保留了i 的 0 至 4 位,相当于 i % 32 ,然后把 1 左移这么多位,定位到相应的 int 中所对应的那一位

 a[ i >> SHIFT ]   |=   (1<<( i & MASK) ) ;//位设置

}

void clr(int i)

{

 a[ i >> SHIFT ]   &=  ~  (1<<( i & MASK) ) ;//清零

}

int  test (int i)

{

  return a[ i >> SHIFT ]   & (1<<( i & MASK) ) ;//同1做与,结果为0则原位为0,不为0则原位为1

}







0 0