位图和哈希切分的大数据处理

位图是一个数组的每个数据的每个二进制位表示一个数据,0表示数据不存在,1表示数据存在;

在现实生活中,大数据的处理十分的常见;比如说,给40亿个不重复的无符号整数,没排过序,如何快速判断一个数是否在这40亿个数中?

要解决这个问题,我们首先想到的是先排序,在进行二分查找,很容易就可以判断成功。但是排序并不好排,40亿个数据,让我们来算一算需要多少的内存,40亿*4字节 =  4G*4 = 16G;一般的电脑都是4G,8G;一次处理16G的数据显然是不可能了;这就需要用位图来解决这类的问题了;

要表示40亿个数据,一个数据4个字节,32个二进制位,用一个二进制位来表示一个数是否存在的状态,这就需要500M左右的内存;显然这是可以接受的;具体看下图:

位图和哈希切分的大数据处理_第1张图片

实现代码如下

//位图
class BitSet
{
public:
	BitSet(const size_t range)
	{
		_a.resize((range>>5) + 1);
	}

	void Set(size_t num)  //将num记录;
	{
		size_t index = num >> 5;
		size_t pos = num % 32;

		_a[index] |= (1 << pos);
	}

	void Reset(size_t num)  //删除num记录
	{
		size_t index = num >> 5;
		size_t pos = num % 32;

		_a[index] &= ~(1 << pos);
	}

	bool Test(size_t num) //判断num是否存在;
	{
		size_t index = num >> 5;
		size_t pos = num % 32;

		//判断这这个位,0不存在,1存在;

		return _a[index] & (1 << pos);
	}


protected:
	vector _a;
};
解决上述问题的测试用例:

void TestBitSet()
{
	BitSet bs(-1); //-1转换后就是整数表示的最大范围;
	bs.Set(1);
	bs.Set(3);
	bs.Set(4);
	bs.Set(8);
        //.... 向后的40亿数据
	cout << bs.Test(1) << endl;
	cout << bs.Test(10) << endl;
}
让我们继续深入,看看另外一个问题:

给一个超过100G大小的log file,log中存着ip地址,设计算法找到出现次数最多的IP地址?

一次处理100G,计算机想想就压力巨大,我们可以将其划分位计算机能处理的大小进行处理,比如以1G为单位划分位100份,一份一份进行处理,就可达到目的,但是怎么划分是个难题;

第一种思路:可以将100G等分划分位100份,每一份单独处理,但是这个会遇到一个问题,有些想同的IP地址是在不同的等分块中,统计的结果不是正确的结果;

第二种思路:利用哈希切分,可以划分成100份,重点是使相同IP进入一个编号相同的小文件;这就避免了相同IP地址分散在不同小文件的问题;
位图和哈希切分的大数据处理_第2张图片


你可能感兴趣的:(数据结构)