bitmap算法简介

标签: bitmap 算法 简介 | 发表时间:2015-03-20 20:18 | 作者:a130737
出处:http://blog.csdn.net

今天看到海量数据处理算法————bitmap(又称为bitset, 或者bit array), 有意思的算法。

C++ 有一个头文件是<bitset>。 

bitmap的思想就是数据压缩。 用一个二进制bit(0或者1)去标记某个元素对应的value, 这就是bit + map啊。

由于使用bit单位存储数据, 所以可大大节省内存空间。下面举一个使用bitmap 的例子。

我们要对0-7内的五个元素进行排序, 假设这5个元素为(4, 7, 2, 5, 3)。 假设元素没有重复的。 要表示8个数, 我们需要8个bit。也就是1byte.

下面我们只需要开辟1byte的空间, 对这个1byte的所有的bit都初始化为0。

如下: 0000 0000

我们可以规定, 有如下的map。 

0000 0000 ---> 0

0000 0010 ---> 1

0000 0100 ---> 2

0000 1000 ---> 3

0001 0000 ---> 4

0010 0000 ---> 5

0100 0000 ---> 6

1000 0000 ---> 7

以上的map是我们默认的, 不需要去另外开辟空间存这个映射表格(不过我们也可以吧index设为从1开始, 就有如下映射:

0000 0001 ----> 1

0000 0010 ----> 2

.............................

1000 0000 -------> 8

)

试着想想, 如果我们直接存放, 需要 8 x sizeof(int) = 32byte。

但是由于我们使用了bitmap, 我们只需要8 x 1 bit = 1byte既可以。 好节省空间啊。 节省32倍。 太牛了。

下面我们就应用这一个byte存储着5个元素, 得到的存储信息如下:

首先, 输入第一个元素4, 对应如下:

0001 000.

第二个元素输入是7, 所以将第8位设置为1, 变成如下:

1001 0000

最终, 如下:

1011 1100代表着所有的元素4, 7, 2, 5, 3。

然后我们遍历一遍bit区域, 将改为编号是1的编号(索引)输出, 就是(2, 3, 4, 5, 7)。

#include <bitset>
#include <iostream>

using namespace std;

int main() {
    int arr[5] = {4, 7, 2, 5, 3};
    bitset<8> mybit; // default constructor all to 0

    for(int i = 0; i < 5; ++i) {
        mybit.set(arr[i]); // set bit arr[i], 即置1
    }

    cout << mybit << endl;

    cout << "sorting using bitmap: ";
    for(int i = 0; i < 8; ++i) {
        if(mybit[i]) {
            cout << i << " ";
        }
    }
}

运行结果如下:

这样, 我们就在O(n)的线性时间内完成了排序操作。 太好了, 就想counting sort的性能。 


注意, 使用bitmap 的前提是出现的元素不重复的, 这是这个算法的缺点。

现在在举一个bitmap算法例子。

使用bitmap 实现8位(表示10进制位)电话号码的存储, 插入, 查找, 删除等操作。

分析:    首先, 我们知道, 8位电话号码总共有0----999999999个号码。 我们使用bitmap的办法, 每一个bit(二进制位)代表一个8个数字的电话号码。

需要 100000000bit = 100000000/8 = 12500000bytes的内存进行存储, 也就是12.5M的内存空间进行存储。

关键是map的映射表, 如下:

我们需要申请的内存大小为 :

int arr[1 + N / 32], 我们当然可以使用<bitset>下面的bitset class了,但是这里重新造轮子, 只是为了说明原理。

arr[0]在内存中占用32bit, 可以对应0 - 31, 依次类推, bitmap 表如下:

arr[0] ------> 0 --- 31

arr[1] -------> 32 -- 63

arr[2] --------> 64 -- 95

arr[3] ---------> 96 --- 127

...........................

就这样, 完成了映射。 


bitmap的应用如下:

(1)可进行数据的快速查找,判重,删除,一般来说数据范围是int的10倍以下

(2)去重数据而达到压缩数据


 int型变量a的第k位清0,即a=a&~(1<<k)
 将int型变量a的第k位置1, 即a=a|(1<<k)

已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数。

8位最多99 999 999,大概需要99m个bit,大概10几m字节的内存即可。 (可以理解为从0-99 999 999的数字,每个数字对应一个Bit位,所以只需要99M个Bit==1.2MBytes,这样,就用了小小的1.2M左右的内存表示了所有的8位数的电话)。 去重, 使用bitmap 线性时间就可以了。


2)2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。 
将bit-map扩展一下,用2bit表示一个数即可,0表示未出现,1表示出现一次,2表示出现2次及以上,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。或者我们不用2bit来进行表示,我们用两个bit-map即可模拟实现这个2bit-map,都是一样的道理。


作者:a130737 发表于2015/3/20 14:04:24 原文链接
阅读:36 评论:0 查看评论

相关 [bitmap 算法 简介] 推荐:

bitmap算法简介

- - CSDN博客推荐文章
今天看到海量数据处理算法————bitmap(又称为bitset, 或者bit array), 有意思的算法. C++ 有一个头文件是. bitmap的思想就是数据压缩. 用一个二进制bit(0或者1)去标记某个元素对应的value, 这就是bit + map啊. 由于使用bit单位存储数据, 所以可大大节省内存空间.

Bitmap算法原理

- - 互联网旁观者
【什么是 Bit-map 】. 所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素. 由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省. 如果说了这么多还没明白什么是Bit-map,那么我们来看一个具体的例子,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).

Bitmap优化

- - CSDN博客推荐文章
一个进程的内存可以由2个部分组成:. dalvik就是我们平常说的. java堆,我们创建的对象是在这里面分配的,而. Java后,以后这块内存即使释放后,也只能给. Java突然占用了一个大块内存,. malloc进行内存分配的,占用的是. C的内存,这个也就说明了,上述的. 4MBitmap无法生成的原因,.

Bitmap的秘密

- - 博客园_知识库
  之前已经参加过几次QCon峰会,不过今年QCon 2014 上海峰会对我来说比较特别,不再只是一名听众,而是第一次登台演讲. 感觉的确不太一样,一来是身份从听众变成了讲师,二来是因为成了讲师,让我接触到更多的业内朋友,也遇到了更多的提问、咨询. 会后已经有一段时间了,还有朋友提出想了解更多的技术知识.

Redis中bitmap的妙用

- - IT瘾-tuicool
在Redis中我们经常用到set,get等命令,细心的你有没有发现,还有几个相似的命令叫setbit,getbit,它们是用来干嘛的. 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身. 我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间.

bitmap索引的深入研究

- - 数据库 - ITeye博客
位图(bitmap)索引是另外一种索引类型,它的组织形式与B树索引相同,也是一棵平衡树. 与B树索引的区别在于叶子节点里存放索引条目的方式不同. 从前面我们知道,B树索引的叶子节点里,对于表里的每个数据行,如果被索引列的值不为空的,则会为该记录行在叶子节点里维护一个对应的索引条目. 而位图索引则不是这样,其叶子节点里存放的索引条目如下图所示.

AndroidのBitmap之大图片优化

- - 博客园_首页
不解释大家懂得,在listview 或grid或viewpager等大量大尺寸图片时,会造成OOM. 这里是优化图片内存的一个方法,注释写的很 明确... public Bitmap getBitmapFromNet(final String url,final int width,final int height){//从网络下载图片.

redis 用setbit(bitmap)统计活跃用户

- - 编程语言 - ITeye博客
Redis支持对String类型的value进行基于二进制位的置位操作. 通过将一个用户的id对应value上的一位,通过对活跃用户对应的位进行置位,就能够用一个value记录所有活跃用户的信息. 如下图所未,下图中的bitmap有9个位被置为1,表示这9个位上对应的用户是今天的活跃用户. 其中第15位表示uid为15的用户,第一位表示uid为0的用户.

xUtils 1.6.6 (Android工具库) 发布 - Bitmap模块优化

- - 开源中国社区最新新闻
感谢关注xUitls的网友最近一段时间给予的热心反馈,xUtils近期在bitmap模块进行了很多优化,同时修复和优化了大家反馈的一些问题.         更多介绍,源码和示例代码下载:https://github.com/wyouflf/xUtils.         详细更新记录见:https://github.com/wyouflf/xUtils/commits/master.

Android上在两个Activity之间传递Bitmap对象

- - CSDN博客推荐文章
Android上在两个Activity之间传递Bitmap对象. 1.  HTTP客户端下载图片,通过ImageView对象显示. 2.  把ImageView上的Bitmap对象从当前Activity传递到另外一个. 3.  基于串行化传递Java对象数据. 首先看我是怎么实现HTTP客户端下载图片,通过异步Task接口实现HTTP客户端下载图片并通过Handler来更新ImageView,代码如下:.