//**********************位图***********************
//腾讯面试题:
// 给40亿个不重复的无符号整数,没排过序,给一个无符号整数如何
// 快速判断这个数是否在这40亿个数中
//解题思路:
//(1)直接存进内存
//40亿个无符号数,如果放到内存,就需要开辟4*4G=16G的空间,因为数的范围不确定,所以
//开辟尽可能大的空间来存放,需42亿9千万×4字节的空间
//(2)位图
//位图:在一块内存区域的每个比特存0或1,表示其对应的元素不存在或者存在
//位图优点: 速度快,内存空间占用小,能表示大范围的数据
//比较:用位图的话,需(42亿9千万×4字节)/32字节=大约500M的空间内存就可以
// 把40亿个数全部放进内存
//按位与&:都为真时才为真,即都为1时才为1
//按位或|:都为假时才为假,即都为0时才为0
//按位异或^:两个数不同时为1
//左移<<是往高位移 如在一个从0到31的比特位中,让1<<2,则比特位变为00100000 00000000 00000000 00000000
//右移>>是往低位移 x>>1等于x/2 x>>5等于x/32
#include
<iostream>
#include
<vector>
using
namespace
std;
class
BitMap
{
public
:
BitMap(
size_t
range
)
:size(0)
{
arr.resize((
range
>> 5) + 1);
}
//把某个数对应的比特位标记为1表示这个数存在
bool
Set(
size_t
data
)
{
//找data对应的比特位
size_t
index =
data
>> 5;
size_t
num =
data
% 32;
//arr是vector类型的,会被自动初始化为0
//1<<num时只有一位为1,其余都为0,当数据对应的比特位为0时进入循环,防止对一个数据进行多次标记,使size和实际数据不符
if
(!(arr[index] & (1 << num)))
{
arr[index] |= (1 << num);
//arr中的值与(1 << num)保证了已经被标记为1的地方不变
++size;
return
true
;
}
else
{
return
false
;
}
}
bool
Reset(
size_t
data
)
{
//找data对应的比特位
size_t
index =
data
>> 5;
size_t
num =
data
% 32;
//当数据对应的比特位为1时进入循环,防止多次Reset,size在一个数上面多次--
if
(arr[index] & (1 << num))
{
arr[index] &= (~(1 << num));
--size;
return
true
;
}
else
{
return
false
;
}
}
bool
Test(
size_t
data
)
{
//找数据对应的比特位
size_t
index =
data
>> 5;
size_t
num =
data
% 32;
//结果为1则存在,结果为0则不存在
return
arr[index] & (1 << num);
}
size_t
Size()
{
return
size;
}
private
:
vector
<
size_t
> arr;
size_t
size;
};
void
TestBitMap()
{
BitMap
bt(10);
bt.Set(9);
bt.Set(5);
cout <<
"9是否存在?"
<< bt.Test(9) << endl;
//1
cout <<
"6是否存在?"
<< bt.Test(6) << endl;
//0
//bt.Reset(9);
//cout <<"9是否存在?"<< bt.Test(9) << endl;
bt.Set(7);
bt.Set(7);
bt.Set(7);
cout <<
"7是否存在?"
<< bt.Test(7) << endl;
//1
cout <<
"size="
<< bt.Size() << endl;
//3
bt.Reset(7);
bt.Reset(7);
bt.Reset(7);
cout <<
"7是否存在?"
<< bt.Test(7) << endl;
//0
cout <<
"size="
<< bt.Size() << endl;
//2
}
int
main()
{
TestBitMap();
return
0;
}
![]()
![]()

![]()