bitmap与2-bitmap使用总结
来源:互联网 发布:现在的网络电视哪种好 编辑:程序博客网 时间:2024/05/22 16:50
bitmap是一种简单的数据结构,但在存储空间压缩方面却使用广泛。
bitmap就是用一个bit位来标记某个元素是否存在:1表示存在,0表示不存在;而2-bitmap就是用两个bit为来标记某个元素出现的次数:00出现0次,01出现1次,10出现2次及其以上,11无意义。
2-bitmap在内存中的表示如下:
[0] [1] [2] ……
|00 00 00 00|00 00 00 00|00 00 00 00| ……
3 2 1 0 7 6 5 4 11 10 9 8 ……
任何一个可采用数组作为辅助标记来解决的问题都可以用bitmap来解决,因为用数组的每一个元素作为标记的话,用bit同样可以作为标记。当数据量比较小时,有时候为了操作方便,可直接采用数组。但当数据量很大的时候,因为内存大小的原因或题目限定了可用内存大小,数组就再没法解决我们的问题, 而此时bitmap就显示出其空间压缩的威力了:如果用char型的数组,标记同样范围内的数bitmap最多可以节省8倍空间,2-bitmap可节省4倍空间。若采用int型的数组,bitmap和2-bitmap可以分别最多节省32倍、16倍的空间。
bitmap能用来处理以下问题:
(1)、字符串方面
1、C语言str系列库函数之strtok()、strspn()、strcspn()和strpbrk()函数都用到了bitmap。详见C语言str系列库函数之strtok()、C语言str系列库函数之strspn()、strcspn()和strpbrk();
2、判断一个字符串B中的字符是否都在另一个字符串A中出现(网上能搜到)。跟上面第1条博文链接里的十分类似。
3、在一个字符串中找到第一个只出现一次的字符(google面试题、网上能搜到)。
可以用26维的数组统计26个字母出现的次数,然后顺序查找统计表直到查到到结果为1的就是要查到的字符。
也可以采用2-bitmap,更节省空间。
(2)、大数据
1、在2.5亿个整数找出不重复的整数,内存不足以容纳着2.5亿个整数
2、腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
对于问题1,整数可能是正数也可能是负数,首先只考虑正整数情况,采用2Bitmap方法,用00表示不存在,01表示出现1次,10表示出现2次及以上,此方法总共需要的内存2^31*2bit = 1Gb = 128MB(32位的正整数有2^31个,每个存储需要2bit,所以就是1Gb,换成字节就是128MB),这样内存就应该能够容纳了,最后在处理完所有的数后,只要输出对应位为01的数即可。如果这2.5亿个数里面既有正数又有负数那么就用两个2Bitmap分别存储正数和负数(取绝对值存储),零就随便放,这是所需要的内存是256MB。
对于问题2,直接用Bitmap即可,0表示存在,1表示不存在。
更多关于用bitmap来解决问题的博文:十七道海量数据处理面试题与Bit-map详解、http://blog.csdn.net/v_july_v/article/details/7382693
2-bitmap的使用关键在于如何操纵位,下面是一个示例代码:
#include <stdio.h>#include <memory.h>#include <stdlib.h>#define N 1024*1024*1024unsigned char bitmap[1 + N / 4]; //2-bitmapvoid set(int x,int num){ int m = x >> 2;//x / 4; int n = x & 0x3;//x % 4; //bitmap[m] &= ~((0x3<<(2*n)) & 0xff); //bitmap[m] |= ((num&0x3)<<(2*n) & 0xff);bitmap[m] &= ~(0x3 << (2*n));bitmap[m] |= ((num & 0x3) << (2*n));}void clear(int x){int m = x >> 2;//x / 4; int n = x & 0x3;//x % 4; //bitmap[m] &= ~((0x3<<(2*n)) & 0xff); //0xff可以去掉bitmap[m] &= ~(0x3 << (2*n));}unsigned get(int x){int m = x >> 2;int n = x & 0x3;return (bitmap[m] & (0x3 << (2*n))) >> (2*n);}void add(int x){set(x, get(x) + 1);}int main(){int a[8] = {1, 3, 1, 4, 5, 5, 5, 5}; //找出数组a中不重复的元素memset(bitmap, 0, sizeof(bitmap)); //清空位图for (int i = 0;i < 8; i++){unsigned val = get(a[i]);//00、01、10if (val <= 1) //a[i]在bitmap的位序列为10时表示出现最少2次set(a[i], val+1);}//现在可以查看每个元素出现的次数for (int i = 0;i < 8; i++)printf("%d %d\n", a[i], get(a[i]));putchar('\n');//如果要判断某个数x是否存在于数组a中,直接判断get(x)的值//get(x) > 0 ? 存在 : 不存在//下面的代码输出在a数组中仅出现1次的数for (int i = 0; i < 2;i++) //这里实际上只需要用到16bitfor(int j = 0; j < 4; j++){int x = (i << 2 | (j & 0x3)); //得到存在这个位置的数是多大int val = get(x);if (val == 1)printf("%d ", x);}getchar();return 0;}
参考:http://blog.csdn.net/acceptedxukai/article/details/9025493
- bitmap与2-bitmap使用总结
- bitmap与2bitmap实现
- bitmap与2bitmap实现
- bitmap与2bitmap实现
- Bitmap---Bitmap用法总结
- Android bitmap实际使用总结
- Bitmap总结
- Bitmap总结
- Bitmap总结
- bitmap总结
- Bitmap 的分析与使用
- Bitmap的分析与使用
- Bitmap使用
- Bitmap 使用
- bitmap使用
- 使用bitmap
- Bitmap使用
- Bitmap
- 5 java构造器的解释和认识
- 极速体验,国产编程语言R++1.81内测版发布
- win7 关闭IE 弹窗和安全警报
- Error与Exception有什么区别
- Linux内核源码分析--内核启动命令行的传递过程(Linux-3.0 ARMv7)
- bitmap与2-bitmap使用总结
- Java SecurityManager相关概念理解
- partial_sort
- 道而弗牽,強而弗抑,開而弗達》
- oracle创建表时,先判断表是否存在
- Swift语言学习3--对象和类
- 进程同步互斥——不死锁的哲学家问题
- html5权威指南 学习笔记(1) 之 新增的主体结构元素
- Eclipse的Vim插件viPlugin的安装