《编程珠玑》第一章 位图在大量数据中的使用

书中提到了产生大量不重复数据的需要:
产生NUM个N内的32位数字
	for (i = 0;i < NUM;++ i)
	{
		temp = (double)rand()/(RAND_MAX+1)*N;
		bits = temp / BITSPERWORD;
		n = temp % BITSPERWORD;
        while (a[bits] & (1<<n))                 //already existing number
        {
			//就近选择
			if (temp >= N)
			{
             temp = 0;
	 		} 
			else
			{
				temp ++;
			}
			//下述策略效率太慢
			//temp += (double)rand()/(RAND_MAX+1)*N;
			//temp %= N;
			bits = temp / BITSPERWORD;
			n = temp % BITSPERWORD;
        }
		outfile<<temp<<" ";
		a[bits] |= (1<<n);                             //set to 1
	}

上述位图标识采用的是才用开辟一定int型数组使用的,其中BITSPERWORD=32.
其中,在数据产生达到千万以上或是N和NUM相差不多,第一种策略会是机器跑个没停,所以,使用了就近原则,以使尽快找到不重复数据。
当然,我们还可以使用vs2008中stl中的位图数据类型,需包含头文件:
#include <bitset>


位图的使用:
bits.test(pos)           //检测是否为一
bits.set(pos)            //置1
bits.reset(pos)          //置0


然后,排序的方法与上述位图思路相同,(毕竟,没法一下对这么多数字一起处理,故应一个个从磁盘读取,标识,然后再读取数据)。

不过,当数据很大时,效率还是很低的,例如:
当产生亿计的数据,需要花费大概5~6小时。
如果要产生第二章所需的2^32内40亿个数据,时间可想而知。

另外,在数据排序的时候,如果内存有限制,比如只有几M字节使用,而上述产生2^32数据量时需开辟512M空间,即使亿计的数据量,也要仅百M的空间,如此我们需要采用通道技术。
K通道在Kn时间和n/k空间内排序:
将数据分为几个部分,分别读取磁盘,每次访问一定大小范围的数据,最终标记完所有数据。

你可能感兴趣的:(编程,C++,c,C#)