Bit-Map
昨日读July大神《教你如何迅速秒杀掉:99%的海量数据处理面试题》博客,有这么一题与大家分享:
给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
July给出思路,位图/Bitmap方法,未闻,遂学之。
1.map类型
map是“键-值”对的集合。map类型通常可理解为关联数组:可使用键作为下表来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
--引自《C++ Primer中文版》pp.309
这里讲map的概念并不是要介绍map这个容器,而是引入map类型数据结构,即“key-value”。
2.Bit-Map
所谓Bit-Map,就是用一个bit位来标记某个元素对应的value,而key即是该元素。
比如上题,若是用int型数组存储,每个数据占4个字节,那么40亿个数就是160亿字节,需要16g的内存;而用Bit-Map,以bit为单位存储数据,每个数据占1bit,40亿bit也就是512m(1B=8bit),因此能够有效节约存储空间。
给一个例子:现在我们有一个数组(4,7,2,5,3),现在我们要用Bit-Map来存储。最大的数为7,所以我们需要8个bit来存储,开辟1B的空间,将所有bit位(key=0~7)置为0(value=0),如下图:
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置置为1(p+(i/8)|(0x01<<(i%8))),即右数第4个为1:
| 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
依次类推,遍历结束:
| 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 |
好了,我们只用1B空间存储了5个数,大大节约存储空间。
简单实现本文开头的题目,代码如下:
//written by 七年之后
//2013.09.06于行政北楼 #include<iostream>
using namespace std; #define BYTE_SIZE 8
#define MAX 4000000000 void Bit_Map_Insert(char *bitmap,unsigned int data)
{
bitmap+=data/BYTE_SIZE;
*bitmap=(*bitmap)|(0x01<<(data%BYTE_SIZE));
} void Bit_Map_Search(char *bitmap,unsigned int data)
{
bitmap+=data/BYTE_SIZE;
if((*bitmap)&(0x01<<(data%BYTE_SIZE)))
cout<<data<<" exist."<<endl;
else
cout<<data<<" doesn't exist."<<endl;
} void Bit_Map_Delete(char *bitmap,unsigned int data)
{
bitmap+=data/BYTE_SIZE;
if((*bitmap)&(0x01<<(data%BYTE_SIZE)))
{
*bitmap=(*bitmap)&(~(0x01<<(data%BYTE_SIZE)));
cout<<data<<" has deleted."<<endl;
}
else
{
cout<<data<<" doesn't exist."<<endl;
}
} int main()
{
char *bitmap;
bitmap=new char[+MAX/BYTE_SIZE];
memset(bitmap,,sizeof(bitmap)); /*测试数据*/
unsigned int data_array[]={,,,,,,,,,,
,,,,
,};
for(int i=;i<sizeof(data_array)/;i++)
Bit_Map_Insert(bitmap,data_array[i]); Bit_Map_Search(bitmap,);
Bit_Map_Search(bitmap,);
Bit_Map_Search(bitmap,);
Bit_Map_Search(bitmap,); Bit_Map_Delete(bitmap,);
Bit_Map_Search(bitmap,); return ;
}

本文如有任何疑问、错误,欢迎与我联系,谢谢!(转载请说明出处)
参考:
1.《C++ Primer 中文版》
2.http://wenku.baidu.com/view/24afb520ccbff121dd368308.html
Bit-Map的更多相关文章
- mapreduce中一个map多个输入路径
package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...
- .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法
.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...
- Java基础Map接口+Collections工具类
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- Java基础Map接口+Collections
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- 多用多学之Java中的Set,List,Map
很长时间以来一直代码中用的比较多的数据列表主要是List,而且都是ArrayList,感觉有这个玩意就够了.ArrayList是用于实现动态数组的包装工具类,这样写代码的时候就可以拉进 ...
- Java版本:识别Json字符串并分隔成Map集合
前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...
- MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析
在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...
- MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程
在上一节我们分析了TaskTracker如何对JobTracker分配过来的任务进行初始化,并创建各类JVM启动所需的信息,最终创建JVM的整个过程,本节我们继续来看,JVM启动后,执行的是Child ...
- MapReduce剖析笔记之五:Map与Reduce任务分配过程
在上一节分析了TaskTracker和JobTracker之间通过周期的心跳消息获取任务分配结果的过程.中间留了一个问题,就是任务到底是怎么分配的.任务的分配自然是由JobTracker做出来的,具体 ...
- MapReduce剖析笔记之三:Job的Map/Reduce Task初始化
上一节分析了Job由JobClient提交到JobTracker的流程,利用RPC机制,JobTracker接收到Job ID和Job所在HDFS的目录,够早了JobInProgress对象,丢入队列 ...
随机推荐
- Linux中printf格式化输出
printf使用文本或者由空格分隔的参数,我们可以在printf中使用格式化字符串.printf不会写像echo那样自动添加换行符,必须手动添加 =========================== ...
- Python数学运算
python中的加减乘除比其他的语言简单,不需要对其赋值变量 (1)加减乘除 ) #加法 ) #减法 ) #乘法 ) #除法 5.0 ) #乘方 (2)判断 判断返回的是True或者False ) # ...
- [原创]PostgreSQL Plus Advanced Server监控工具PEM(四)
四.PEM管理工具 1.编辑配置 选择进行管理的目标服务器,点击菜单Tools->Server Configuration->postgresql.conf管理服务器配置,可以看到我们经常 ...
- ios中用drawRect方法绘图的时候设置颜色
设置画笔颜色可以直接 [[UIColor grayColor] set];就可以设置颜色.
- http压力测试
一.http_load程序非常小,解压后也不到100Khttp_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把 ...
- C#的winform矩阵简单运算
C#的winform矩阵简单运算 程序截图 关键代码 using System; using System.Collections.Generic; using System.ComponentMod ...
- oracle11g创建数据库最后一步确定时弹出无法创建目录
总的说是Windows7的权限问题 Windows7 dos命令下输入dbca创建数据库,因为权限问题,数据库将无法完成.所以还是在开始程序中打开dbca创建数据库比较好. Windows7 dos以 ...
- VC++程序中加入自定义声音(PlaySound函数用法)
VC++编程中,我们可以为自己的程序加入音乐,比如当我们按下一个按钮时或者启动程序时,播放一小段音乐. 该功能用到函数: BOOL PlaySound(LPCSTR pszSound, HMODULE ...
- git创建分支并提交项目
git 创建分支, 切换分支, 合并分支, 删除分支及提交[commit提交到本地仓库push名利提交到远程服务器], 检出[pull], 冲突修改, 本地仓库同步远程服务器[pul和push命令l] ...
- Daily Scrum5
总体来说,我们今天的工作遇到了一些阻碍.前期的对于代码的大量阅读并没有使我们的进度突飞猛进.今天我们完成了关于敏感词汇辨别优化和防滥用部分的代码(之后会有微博来详细介绍),但是我们无法运行程序并测试, ...