您的位置:首页 > 编程语言 > C语言/C++

bit-map简介及其C/C++代码实现

2015-06-13 11:29 561 查看
        在本文中, 我们来介绍一下bit-map,你可别以为这是什么bitmap图像, 那本文要介绍的bit-map是什么呢? 且听我慢慢道来。

        坐过火车没? 当你在火车上, 想拉屎的时候, 你得去上厕所啊。 屁颠屁颠爬到厕所处, 发现上面亮了一个灯, 表示里面有人, 你郁闷至极, 但无可奈何。 过了很久, 那个人出来了, 那个灯也就熄灭了, 你就可以上厕所了。

        这个灯, 就是计算机中的一个bit, 有两种状态 , 1表示有人在厕所中, 0表示没有人在厕所中。 所以, 从这个意义上说, 一个bit可以标志某事物的一个状态, 当这个bit与某事物状态建立映射后, 我说们, 形成了一个bit到事物状态的map.

         

        我们知道, 一个unsign char有8bit, 也就是说, 一个无符号字符可以标志某个厕所的8个坑位的状态, 下面我们看看程序:

#include <iostream>
using namespace std;

int main(void)
{
unsigned char c;

// 8个坑位都没有人
c = 0;

// 8个坑位都有人
c = 255;

// 第1个(也可以认为是第0个)坑位有人
c = 128;

// 最后两个坑位有人
c = 3;

return 0;
}
      看到没? 一个bit标志一个坑, 标志一个事物的状态, 那么一个unsigned char标志着8个事物的状态。 同理, 一个unsigned int标志着32个事物的状态, 其实一个int也可以标志着32个事物的状态。(当然, 这里所说的状态都是二值状态)

       现在, 假设有N个事物状态, 那至少需要多少个int来表示呢? 很显然是 N/32 + 1. 假设有100个事物(N=100), 那至少需要4个int (总共128位). 说的有点多了, 直接看程序吧:

#include <iostream>
using namespace std;

#define BIT_INT 32   // 1个int可以标志32个坑
#define SHIFT 5
#define MASK 0x1f
#define N 100
int a[1 + N / BIT_INT]; // 需要1 + N / BIT_INT 个整数来标志N个事物

// 将所有位都初始化为0状态
void setAllZero()
{
memset(a, 0, (1 + N / BIT_INT) * sizeof(int));
}

// 设置第i位为1, 表示有人在厕所里面
void setOne(int i)
{
a[i >> SHIFT] |= (1 << (i & MASK));
}

// 设置第i位为0, 表示没有人在厕所里面
void setZero(int i)
{
a[i >> SHIFT] &= ~(1 << (i & MASK));
}

// 检查第i位的值, 看看有没有人在厕所里面
int getState(int i)
{
return (a[i >> SHIFT] & (1 << (i & MASK))) && 1;
}

int main(void)
{
int bitNumber = (1 + N / BIT_INT) * BIT_INT;
cout << bitNumber << endl;

setAllZero();
int i = 0;
for(i = 0; i < bitNumber; i++)
{
cout << getState(i);
}
cout << endl;

setOne(0);
setOne(1);
setOne(2);
setOne(3);
setOne(4);
for(i = 0; i < bitNumber; i++)
{
cout << getState(i);
}
cout << endl;

setZero(0);
setZero(1);
setZero(2);
for(i = 0; i < bitNumber; i++)
{
cout << getState(i);
}
cout << endl;

return 0;
}
      看看结果吧:

128

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

11111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

00011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

   

     果然, 结果与预期符合。

     我们再看程序:

#include <iostream>
#include <set>
using namespace std;

#define BIT_INT 32   // 1个int可以标志32个坑
#define SHIFT 5
#define MASK 0x1f
#define N 100
int a[1 + N / BIT_INT]; // 需要1 + N / BIT_INT 个整数来标志N个事物

// 产生伪随机数
unsigned  int getRandom()
{
return rand();
}

// 将所有位都初始化为0状态
void setAllZero()
{
memset(a, 0, (1 + N / BIT_INT) * sizeof(int));
}

// 设置第i位为1, 表示有人在厕所里面
void setOne(int i)
{
a[i >> SHIFT] |= (1 << (i & MASK));
}

// 设置第i位为1, 表示没有人在厕所里面
void setZero(int i)
{
a[i >> SHIFT] &= ~(1 << (i & MASK));
}

// 检查第i位的值, 看看有没有人在厕所里面
int getState(int i)
{
return (a[i >> SHIFT] & (1 << (i & MASK))) && 1;
}

int main(void)
{
int r = N;
int size = 40; // 假设有40个事物(数字), 他们在[0, N-1]这个区间内

// 构造40个互不相等的事物, 实际上, s中的元素是有序的, 但在该程序中, 我们不需要太关注这个
set<int> s;
while(size != s.size())
{
s.insert(getRandom() % r);
}

// 将所有坑位的人赶出来, 初始化
setAllZero();

set<int>::iterator it;
for(it = s.begin(); it != s.end(); it++)
{
setOne(*it); // 将事物*it与其对应的坑位*it联系起来, 当*it这个事物存在时, 对应的坑位*it的状态为1
cout << *it << " ";
}
cout << endl;

int i = 0;
int bitNumber = (1 + N / BIT_INT) * BIT_INT;
for(i = 0; i < bitNumber; i++)
{
cout << i << "对应的坑位状态为:--->" << getState(i) << endl; // 获取坑位状态
}
cout << endl;

return 0;
}


      结果为:

0 2 3 4 5 11 12 16 18 21 22 24 26 27 33 34 35 36 38 41 42 45 47 53 58 61 62 64 67 69 71 73 78 81 82 91 92 94 95 99

0对应的坑位状态为:--->1

1对应的坑位状态为:--->0

2对应的坑位状态为:--->1

3对应的坑位状态为:--->1

4对应的坑位状态为:--->1

5对应的坑位状态为:--->1

6对应的坑位状态为:--->0

7对应的坑位状态为:--->0

8对应的坑位状态为:--->0

9对应的坑位状态为:--->0

10对应的坑位状态为:--->0

11对应的坑位状态为:--->1

12对应的坑位状态为:--->1

13对应的坑位状态为:--->0

14对应的坑位状态为:--->0

15对应的坑位状态为:--->0

16对应的坑位状态为:--->1

17对应的坑位状态为:--->0

18对应的坑位状态为:--->1

19对应的坑位状态为:--->0

20对应的坑位状态为:--->0

21对应的坑位状态为:--->1

22对应的坑位状态为:--->1

23对应的坑位状态为:--->0

24对应的坑位状态为:--->1

25对应的坑位状态为:--->0

26对应的坑位状态为:--->1

27对应的坑位状态为:--->1

28对应的坑位状态为:--->0

29对应的坑位状态为:--->0

30对应的坑位状态为:--->0

31对应的坑位状态为:--->0

32对应的坑位状态为:--->0

33对应的坑位状态为:--->1

34对应的坑位状态为:--->1

35对应的坑位状态为:--->1

36对应的坑位状态为:--->1

37对应的坑位状态为:--->0

38对应的坑位状态为:--->1

39对应的坑位状态为:--->0

40对应的坑位状态为:--->0

41对应的坑位状态为:--->1

42对应的坑位状态为:--->1

43对应的坑位状态为:--->0

44对应的坑位状态为:--->0

45对应的坑位状态为:--->1

46对应的坑位状态为:--->0

47对应的坑位状态为:--->1

48对应的坑位状态为:--->0

49对应的坑位状态为:--->0

50对应的坑位状态为:--->0

51对应的坑位状态为:--->0

52对应的坑位状态为:--->0

53对应的坑位状态为:--->1

54对应的坑位状态为:--->0

55对应的坑位状态为:--->0

56对应的坑位状态为:--->0

57对应的坑位状态为:--->0

58对应的坑位状态为:--->1

59对应的坑位状态为:--->0

60对应的坑位状态为:--->0

61对应的坑位状态为:--->1

62对应的坑位状态为:--->1

63对应的坑位状态为:--->0

64对应的坑位状态为:--->1

65对应的坑位状态为:--->0

66对应的坑位状态为:--->0

67对应的坑位状态为:--->1

68对应的坑位状态为:--->0

69对应的坑位状态为:--->1

70对应的坑位状态为:--->0

71对应的坑位状态为:--->1

72对应的坑位状态为:--->0

73对应的坑位状态为:--->1

74对应的坑位状态为:--->0

75对应的坑位状态为:--->0

76对应的坑位状态为:--->0

77对应的坑位状态为:--->0

78对应的坑位状态为:--->1

79对应的坑位状态为:--->0

80对应的坑位状态为:--->0

81对应的坑位状态为:--->1

82对应的坑位状态为:--->1

83对应的坑位状态为:--->0

84对应的坑位状态为:--->0

85对应的坑位状态为:--->0

86对应的坑位状态为:--->0

87对应的坑位状态为:--->0

88对应的坑位状态为:--->0

89对应的坑位状态为:--->0

90对应的坑位状态为:--->0

91对应的坑位状态为:--->1

92对应的坑位状态为:--->1

93对应的坑位状态为:--->0

94对应的坑位状态为:--->1

95对应的坑位状态为:--->1

96对应的坑位状态为:--->0

97对应的坑位状态为:--->0

98对应的坑位状态为:--->0

99对应的坑位状态为:--->1

100对应的坑位状态为:--->0

101对应的坑位状态为:--->0

102对应的坑位状态为:--->0

103对应的坑位状态为:--->0

104对应的坑位状态为:--->0

105对应的坑位状态为:--->0

106对应的坑位状态为:--->0

107对应的坑位状态为:--->0

108对应的坑位状态为:--->0

109对应的坑位状态为:--->0

110对应的坑位状态为:--->0

111对应的坑位状态为:--->0

112对应的坑位状态为:--->0

113对应的坑位状态为:--->0

114对应的坑位状态为:--->0

115对应的坑位状态为:--->0

116对应的坑位状态为:--->0

117对应的坑位状态为:--->0

118对应的坑位状态为:--->0

119对应的坑位状态为:--->0

120对应的坑位状态为:--->0

121对应的坑位状态为:--->0

122对应的坑位状态为:--->0

123对应的坑位状态为:--->0

124对应的坑位状态为:--->0

125对应的坑位状态为:--->0

126对应的坑位状态为:--->0

127对应的坑位状态为:--->0

       现在应该完成清楚了bit-map吧, 所谓bit-map, 实际上就是用一个bit去map一个事物的状态(二值状态). bit-map的好处是: 节省空间

       实际上, bit-map在大数据处理中经常会用到, 一些笔试面试题经常考, 后续我们会陆续介绍到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: