位图法,是解决大数据查重的另一方法。
比如,有1亿个整数,整数的最大值不超过一亿,求有哪些元素重复了,谁是第一个重复的?谁是不重复的?内存限制100M.
首先分析:1亿数组=100M条数据,如果用哈希表存储,100M整数占用400M空间,再加上链式哈希表地址,100M整数需要800M内存,现在这个问题不能用哈希表。
位图方法:位图法,就是用一个位( 0 或者 1 )来存储数据的状态,比较适合状态简单,数据量比较大,要求内存使用率低的问题场景。
**思路:**首先需要知道待处理数据中的最大值,然后按照size = (maxNumber / 32)+1 的大小来开辟一个int类型的数组,当需要在位图中查找某个元素是否存在的时候,首先需要计算该数字对应的数组中的比特位,然后读取值, 0 表示不存在, 1 表示已存在 。
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
int main()
{
vector<int> vec{ 12,43,78,90,123,56,7 };
// 定义位图数组
int max = vec[0];
for (int i = 1; i < vec.size(); i++)
{
if (vec[i] > max)
{
max = vec[i];
}
}
cout <<"最大值" << max << endl;
int *bitmap = new int[max / 32 + 1](); // ()表示初始化值
unique_ptr<int> ptr(bitmap); // 智能指针
// 找出第一个重复出现的数字
for (auto key : vec)
{
int index = key / 32;
int offset = key % 32;
if (0 == (bitmap[index] & (1 << offset)))
{
// 表示key没有出现过
bitmap[index] |= (1 << offset);
}
else
{
cout << key << "是第一个重复出现数字" << endl;
}
}
system("pause");
return 0;
}
位图算法缺点:数列中的数据少,但是数值很大,这种情况下不适合用位图方法。比如10个整数,最大值是1亿,这种情况用位图法很浪费内存。
位图算法最适合的场景:数据的个数和序列里面数字的最大值相当。