位图算法
位图法就是bitmap的缩写,所谓bitmap,是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。
应用
1.给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
解决方法:申请512M的内存一个bit位代表一个unsigned int值读入40亿个数,设置相应的bit位读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在。
2.使用位图法判断×××数组是否存在重复
解决办法:判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到 5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。
3.使用位图法进行×××数组排序
解决办法:
首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化为unsigned int来处理,而且取位的时候,数字要减去最小值。
应用1代码实现:
#pragma once
#include<vector>
template<class T>
struct DataType
{
long long operator()(const T&key)
{
return key;
}
};
template<class T>
struct StringType
{
long long operator()(const string&key)
{
long long size = 0;
for (int i = 0; i < key.size(); i++)
{
size += key[i];
}
return size;
}
};
template<class T,class BMFunc=DataType<T>>
class BitMap
{
public:
BitMap(size_t size = 1)
{
_a.resize(size / 32 + 1);
}
~BitMap(){}
void set(T &x)
{
BMFunc bmf;
size_t index = bmf(x)/ 32;
size_t num = bmf(x) % 32;
if (!(_a[index] & (1 << num)))
{
_a[index] |= (1 << num);
_size++;
}
}
void Reset(T x)
{
BMFunc bmf;
size_t index = bmf(x) / 32;
size_t num = bmf(x) % 32;
if (!(_a[index] & (1 << num)))
{
_a[index] &= (~(1 << num));
_size--;
}
}
bool Test(T x)
{
BMFunc bmf;
size_t index = bmf(x)/ 32;
size_t num = bmf(x)% 32;
return _a[index] &(1 << num);
}
protected:
vector<size_t> _a;
size_t _size;
};
应用2代码实现:
bool hasDuplicatedItem(int *a, int len)
{
int length, max, i;
length = len;
max = a[0];
for (i = 1; i < length; i++){
if (a[i] > max)
max = a[i];
}
int *arr;
arr = (int*)malloc(sizeof(int)* (max + 1));
for (i = 0; i < length; i++){
if (arr[a[i]])
return true;
else
arr[a[i]] = 1;
}
return false;
}
应用3代码实现:
void bitmapSort(int *a, int len)
{
int length, max, min, i, index;
length = len;
min = max = a[0];
//找出数组最大值
for (i = 1; i < length; i++){
if (a[i] > max){
max = a[i];
}
if (min > a[i]) {
min = a[i];
}
}
//得到位图数组
int *arr;
arr = (int*)malloc(sizeof(int)* (max - min + 1));
for (i = 0; i < length; i++){
index = a[i] - min;
arr[index]++;
}
//重整a中的元素
int arr_length;
arr_length = max - min + 1;
index = 0;
for (i = 0; i < arr_length; i++){
while (arr[i] > 0){
a[index] = i + min;
index++;
arr[i]--;
}
}
}
转载于:https://blog.51cto.com/10794428/1795103