编程珠玑:1.2 位向量用于大数存储及排序

 

问题描述:
输入的是一个文件,至多包含n个正整数,每个正整数都要小于n,这里n=10^7.
每个正整数都不一样。
大概只有1MB的可用内存。


解析:如果不考虑内存大小限制的话我们可以采用,归并排序。

现在考虑1MB内存大小的限制,应该考虑这1000000个数如何存储占用较小的内存空间。

位图数据结构:代表了有限域中的稠集(dense set),每个元素至多出现一次,没有其他的数据和元素相关联。

但是即使不满足这些条件(例如:

存在多个元素或额外数据时,也可以通过使用有限域的键作为表索引,从而起到关联或对应关系。

现在我们考虑位向量,例如我们可以使用一个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

集合中代表数字的各个位设置为1,而其他的位全部都设置为0.

那么N个数只需要1+N/32 的int类型存储空间 ,对于此题,大概需要1.25MB的空间。已经可以到达很可以接受的范围了。

我们只需要三个函数:清零,设置,测试。接下来就要明白清楚如何进行位操作。

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1f
#define N 10000000
int a[1+N/BITSPERWORD];

void set(int
 i)
{
   a[i
>>SHIFT] |= (1<<(i&
MASK));
}

void clear(int
 i)
{
   a[i
>>SHIFT] &= ~(1<<(i&
MASK));
}

int test(
int i)
{
  
return a[i>>SHIFT] & (1<<(i&
MASK));
}


注释:
i>>SHIFT 相当于 i/32得到对应数组下标;  

i&MASK相当于 i mod 32,得到应该设置在哪位;

1<<(i&MASK) 左移i&MASK位,取得相应的掩码。

 

原文链接:http://hi.baidu.com/liaopeter2009/blog/item/84d431df7a0a4d385882dd31.html

 

你可能感兴趣的:(数据结构,编程,测试,存储)