您的位置:首页 > 编程语言

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

2014-11-21 19:40 183 查看
问题描述:

输入:一个最多包含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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: