海量数据处理第二谈-----位图BitMap


位图的概念:

在C++中,位图是以位来表示整数的结构,普通的整数一个数需要用4个字节来表示,我们可以换种思想,在整个整数的集合范围内,某个整数存在与否,只有两种情况,在或者不在,那么,我们可以考虑只用一个bit位,来表示该整数存在的状态,从而达到节省内存的目的。

位图实例分析:

给一个实际的例子,给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中

我们可以简单计算一下,40亿个整数全部放到内存,需要160亿个字节,粗略计算,大致需要16G的内存,如果我们把每个整数是否出现,转换成用一位来表示它存在的状态,需要5亿个字节,也就是大约500M的内存,对于计算机而言,对内存的节省亦常地重要,这就是位图的一个重要应用。

位图模拟实现:

首先我们考虑位图的结构,实际上也是对数组的封装,只不过我们这里需要的是以bit位为单位进行存放,每一位的状态只有0和1两种,这里用来表示该整数是否在位图内。

我们以一个整形为例,在一个整形的空间,存储【1 6 9 4 12 10】这些数,存储结果应该如下:

这个只给出了两个字节,全可以表示上面的6个整数。

关于位图的底层,这里我们使用vector来模拟实现。

#include <vector>
#include<iostream>
using namespace std;
class BitMap
{
public:
    BitMap(const size_t& range)
    {
        int sz = (range >> 5) + 1;
        _vec.resize(sz);
    }
    void BitSet(const size_t& x)
    {
        int index = x >> 5; // index是x对应位所在的下标
        int num = x % 32; // num是x对应该整形的第多少位
        _vec[index] |= 1 << num;
    }
    void BitReSet(const size_t& x)
    {
        int index = x >> 5; // index是x对应位所在的下标
        int num = x % 32; // num是x对应该整形的第多少位
        _vec[index] &= (~(1 << num));
    }
    bool BitTest(const size_t& x)
    {
        int index = x >> 5; // index是x对应位所在的下标
        int num = x % 32; // num是x对应该整形的第多少位
        return _vec[index] & (1 << num);
    }
protected:
    vector<int> _vec;
};

位图的实现实际上就是进行一系列的位操作,通过位操作找到该整形对应的位,下面给出一组简单的测试用例

void TestBitMap()
{
    BitMap  mp(100);
    mp.BitSet(1);
    mp.BitSet(2);
    mp.BitSet(11);
    mp.BitSet(22);
    cout << "test --<1>" << mp.BitTest(1) << endl;
    cout << "test --<2>" << mp.BitTest(2) << endl;
    cout << "test --<11>" << mp.BitTest(11) << endl;
    cout << "test --<22>" << mp.BitTest(22) << endl<<endl;
    mp.BitReSet(2);
    cout << "test --<1>" << mp.BitTest(1) << endl;
    cout << "test --<2>" << mp.BitTest(2) << endl;
    cout << "test --<11>" << mp.BitTest(11) << endl;
    cout << "test --<22>" << mp.BitTest(22) << endl << endl;
}

源码库中的位图:


在源码库中,有这样一个容器 bitset,和我们这里的bitmap性质基本是一样的,当然,功能要比上面实现的位图大得多。

A bitset is a special container class that is
designed to store bits (elements with only two possible values: 0 or 1,
true or false, ...).

The class is very similar to a
regular array, but optimizing for space allocation: each element occupies only
one bit (which is eight times less than the smallest elemental type in C++:
char).

Each element (each bit) can be accessed individually: for
example, for a given bitset named mybitset, the expression
mybitset[3] accesses its fourth bit, just like a regular array accesses
its elements.

Because no such small elemental type exists in most C++
environments, the individual elements are accessed as special references which
mimic bool elements:

库中提供了一系列的函数操作,除了set、reset、test之外,常用的还有filp<取反操作>,count<统计位为1的个数>。关于bitset的操作,都包含在

#include <bitset>

的头文件中。

位图的分析与扩展:

位图的确用起来会很方便,但并不是任何情况下都需要使用到位图的,位图通常是为了处理大量数据,内存中不足以存放所有的数字才使用的一种数据结构,因为位图也有着一定的缺陷:

1> 它的可读性差

2> 位图在视图节约空间的时候,也伴随着一定的消耗,它要求给最大值和最小值之间的所有数都要占用一个bit位,当数据过于分散而数据量又不至太大的情况,位图其实是一种比较浪费空间的做法。如果最小值为10000,位图开辟出来的前10000个bit位其实就空了出来,没有利用到,之前我们举得例子,40亿个整数,因为无符号整数的最大值就到42.9亿左右,大部分的整数值确定都已经被取到,因此我们采用了位图来实现。

3> 当位图用来存储有符号整数时,有两种解决方案,一种是我们约定好最小值不再从0开始,所有的计算都需要减去有符号整数的最大值,另一种是这里采用两位来存储一个数,用两位来表示正数、负数、不存在三种状态。

试想,如果我们要求统计40亿个无符号整数中,出现两次以上的数该如何处理?

。。。。。。

同样,多加一位标志位,用两个bit位来进行处理,那这样的话,就需要我们自己来实现一个基本的两位为一个单元的位图结构。

除此之外,位图还可用来排序,判重,当然这里仅仅限于无符号整数,和上一节的哈希一样,受限于整数范围确实是个不好的地方,下一谈会提到字符串哈希算法与布隆过滤器,正是由于字符串哈希算法,才使得这些数据结构得以大范围的使用。

关于哈希算法:
    http://muhuizz.blog.51cto.com/11321490/1870717

-----muhuizz整理

时间: 2024-08-26 05:56:32

海量数据处理第二谈-----位图BitMap的相关文章

从hadoop框架与MapReduce模式中谈海量数据处理

前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,觉得它们很是神秘,而神秘的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,觉得Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,最近凡是空闲时,便在看“Hadoop”,“MapReduce”“海量数据处理”这方面的论文.但在看论文的过程中,总觉得那些论文都是浅尝辄止,常常看的很不过瘾,总是一个东西刚要讲到紧要处,它便结束了,让我好生“愤懑

从Hadoop框架与MapReduce模式中谈海量数据处理(含淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇,而神奇的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop","MapReduce""海量数据处理"这方面的论文.但在看论

海量数据处理之从Hadoop框架与MapReduce模式中谈海量数据处理(淘宝技术架构)

几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,觉得它们很是神秘,而神秘的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,觉得Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,最近凡是空闲时,便在看"Hadoop","MapReduce""海量数据处理"这方面的论文.但在看论文的过程中,总觉得那些论文都是浅尝辄止,常常看的很不过瘾,总是一个东

海量数据处理--hash和bit-map

问题实例: 海量日志数据,提取出某日访问百度次数最多的那个IP. 答:对于ip,最多也就2^32个.所以可以很好地通过hash函数映射到内存中,再进行统计. IP最多为2^32个,为4G,一次放入内存中不行,可以采用分而治之的方法,先Hash(IP)/1024,将IP地址分别映射到1024个小文件中,每个文件4M,再将每个小文件中的IP放入内存中,进行hashmap,统计出出现频率最高的那个IP,最后可以得到1024个出现高频的IP,采用冒泡排序,可以迅速找出频率最高的那个IP.1 原理简述:

教你如何迅速秒杀掉:99%的海量数据处理面试题(转)

教你如何迅速秒杀掉:99%的海量数据处理面试题本文经过大量细致的优化后,收录于我的新书<编程之法:面试和算法心得>第六章中,新书目前已上架京东/当当 作者:July出处:结构之法算法之道blog 前言   一般而言,标题含有“秒杀”,“99%”,“史上最全/最强”等词汇的往往都脱不了哗众取宠之嫌,但进一步来讲,如果读者读罢此文,却无任何收获,那么,我也甘愿背负这样的罪名 :-),同时,此文可以看做是对这篇文章:十道海量数据处理面试题与十个方法大总结的一般抽象性总结. 毕竟受文章和理论之限,本文

从Hadoop骨架MapReduce在海量数据处理模式(包括淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇.而神奇的东西常能勾起我的兴趣.在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop"."MapReduce""海量数据处理"这方面的论文.但在看论

关于海量数据处理的相关问题

看过很多面经,里面都会问到海量数据处理的问题.虽然在学校根本遇不到这样的情境,但很多方法还是需要我们去好好了解一下的,也是为了以后的工作做准备吧. 搜集了一些有关海量数据处理的问题和解答,如下: 1.海量日志数据,提取出某日访问百度次数最多的那个IP. 此题,在我之前的一篇文章算法里头有所提到,当时给出的方案是:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计. 再详细介绍下此方案:首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文

转 十道海量数据处理面试题与十个方法大总结

作者:July.youwang.yanxionglu. 时间:二零一一年三月二十六日本文之总结:教你如何迅速秒杀掉:99%的海量数据处理面试题.有任何问题,欢迎随时交流.指正.出处:http://blog.csdn.net/v_JULY_v. 第一部分.十道海量数据处理面试题 1.海量日志数据,提取出某日访问百度次数最多的那个IP. 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采用映射的方法,比如模1000,把整

海量数据处理算法总结【超详解】

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合. 而在能容忍低错误率的应用场合