海量数据处理算法—BitMap(Bitmap Sort)

一、背景

来源:

在Jon Bentley的Programming Pearls一书中,第一列介绍了排序问题。当我们更多地了解问题并清楚地定义它的约束时,解决方案从使用磁盘的合并排序(Merge Sort)转换为更为有效的位图排序(Bitmap Sort)。

所谓的Bitmap Sort 就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。

该算法使用位图(或位向量)来表示一组有限的不同整数。例如,如果我们有一个0-5的整数范围,我们可以使用一个6位数组来表示它,例如:
[2,3,5]变为0 0 1 1 0 1 
[1,3,4]变为0 1 0 1 1 0

再看个简单的问题:

假如给你20亿个非负数的int型整数,然后再给你一个非负数的int型整数 t ,让你判断t是否存在于这20亿数中,你会怎么做呢?

有人可能会用一个int数组,然后把20亿个数给存进去,然后再循环遍历一下就可以了。

想一下,这样的话,时间复杂度是O(n),所需要的内存空间

4byte * 20亿,一共需要80亿个字节,

大概需要8GB的内存空间,显然有些计算机的内存一次是加载不了这么这么多的数据的。

这个时候,Jon Bentley提出了他的思路:

我们在使用byte,int,short,long等这些数据类型在存储数据的时候,他们最小的都要占用一个字节的内存,也就是8个bit,也就是说,最小的操作单位是8个bit。根本就没有可以一个一个bit位操作的数据类型啊。

在C/C++的bitMaP实现中,它采用的是用一个int数据来进行存储的。一个int占用84个字节,即32bit,所以一个int可以存储32个数。例如 arr 是一个int类型的数组,则 arr[0]可以存 0 ~ 31,arr[1]可以存32 ~63,以此类推。

 

二、Bit Map的基本思想

32位机器上,一个整形,比如 int a; 在内存中占32bit,可以用对应的32个bit位来表示十进制的0-31个数,bitmap算法利用这种思想处理大量数据的排序与查询。

优点:

  • 效率高,不许进行比较和移位
  • 占用内存少,比如N=10000000;只需占用内存为N/8 = 1250000Bytes = 1.2M,如果采用int数组存储,则需要38M多

缺点:

  • 无法对存在重复的数据进行排序和查找

示例演示:

我们都知道,一个二进制位,有0和1两种状态,所以说,其实我们是可以用一个二进制位来代表一个int型的数是否存在的。例如对于1,3,5,7这四个数,如果存在的话,则可以这样表示:

首先第一个元素是1,那么就把1对应的位置为1(可以这样操作 p+(i/8)|(0x01<<(i%8)) 当然了这里的操作涉及到big-endian和Little-endian的情况,这里为Big-endian:最高位字节存储在最低的内存地址处),因为是从零开始的,所以要把第五位置为一(如下图):

1代表这个数存在,0代表不存在。例如表中01010101代表1,3,5,7存在,0,2,4,6不存在。

那如果8,10,14也存在怎么存呢?如图,8,10,14我们可以存在第二个字节里

附加:字节顺序,又称端序尾序(英语:Endianness

字节的排列方式有两个通用规则。例如,一个多位的整数,按照存储地址从低到高排序的字节中,如果该整数的最低有效字节(类似于最低有效位)在最高有效字节的前面,则称大端序;反之则称小端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。

小端序(英:little-endian)情况

思想比较简单,关键是十进制和二进制bit位需要一个 map 映射表,把10进制映射到bit位上。

 

三、map映射表

假设需要排序或者查找的总数N=10000000,那么我们需要申请的内存空间为 int a[ N/32 +

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值