大家好,我是蓝胖子,我一直相信编程是一门实践性的技术,其中算法也不例外,初学者可能往往对它可望而不可及,觉得很难,学了又忘,忘其实是由于没有真正搞懂算法的应用场景,所以我准备出一个系列,囊括我们在日常开发中常用的算法,并结合实际的应用场景,真正的感受算法的魅力。

今天,我们就来学习下位图bitmap的原理以及作用。

代码已经上传github

https://github.com/HobbyBear/codelearning/tree/master/bitmap

位图作用

bitmap 是一种高效的且占用内存很小的 判断 某个值 存在与否的数据结构。它用二进制的某一位去表示某个值是否存在。

比如我们需要统计10亿用户是否签到,正常的做法是你可以设计一个10亿长度的map,将用户的uid设置为key,是否签到设计为value,假设uid是int64 类型,占用8个字节,10亿用户就需要大约8G的内存 ,而如果 设计成bitmap去存储,则只需要大约125M 。极大的节约了内存。

原理

因为bitmap中用二进制位代表某个uid是否存在,所以一个字节能够代表8个uid是否存在,如下图所示:

bit位为1代表所在uid的用户已经签到,0则代表未签到。图中,uid为1和5的用户都没有签到,uid为2,3,4,6,7,8的用户都已经签到。

实现

要实现这样一个bitmap,我们可以用一个字节数组来保存所有的bit位,将bit位 设置为1 就是确认某个数字或者说是像例子里的uid,定位uid对应在这个字节数组的哪个位置,将特定位置的字节定位到以后,再定位这个uid在字节中的bit位是在什么位置。

整个过程看代码会更加清晰,如下代码所示,我们在bitmap的构造函数里定义了整个bitmap的最大长度。

type BitMap struct {
flags []byte
} func New(max int64) *BitMap {
flagLen := max/8 + 1
return &BitMap{flags: make([]byte, flagLen)}
}

接着看下它的set方法,找到某个数字index再bitmap中的bit位,将其设置为1,一个字节是8位,通过index/8 得到其bit位是在哪个字节上,通过index%8 取余得到设置的bit位 在字节的第几个bit为上,然后通过或运算将特定bit位设置为1。

func (b *BitMap) Set(index int64) {
arrIndex := index / 8
offset := index % 8
// 将offset位置设置为1,或运算,0 | 1 = 1 1|1= 1, 0|0 =0, 1的| 将原值设置为1 ,0的| 不改变原值
b.flags[arrIndex] = b.flags[arrIndex] | (0x1 << offset)
}

我还定义了Exits 方法快速判断某个值是否被bitmap记录,同样也是先找到index对应的bit位 在数组中的位置,然后通过与运算去判断特定bit位是0还是1。

func (b *BitMap) Exits(index int64) bool {
arrIndex := index / 8
offset := index % 8
res := b.flags[arrIndex] & (0x1 << offset)
if res == 0 {
return false
}
return true
}

除此以外,你还可以定义一个remove方法,用于清除特定bit位上的值,

func (b *BitMap) Clean(index int64) {
arrIndex := index / 8
offset := index % 8
// 0 & 1 = 0 ,0 & 0 = 0, 1&1 =1 1的& 不会改变原来的值, 0的& 将原值变为0
b.flags[arrIndex] = b.flags[arrIndex] & ^(0x1 << offset)
}

你可以看到bitmap用到的位运算其实本质上是用到下面的性质:

1, 1 与 0或者 1的 & 运算不会改变原值, 0 的& 会将特定bit位设置为0。

2, 0的或运算 不会改变原来的值, 1的或运算是将原来的bit位设置为1。

整个实现并不难,但这种结构的确在大数据量下达到了节约内存进行排重的目的,后续讲到的布隆过滤器也是在这种数据结构上实现的。

位图(bitmap)原理以及实现的更多相关文章

  1. (算法)位图BitMap

    题目: 给定一数组,大小为M,数组中的数字范围为1-N,如果某带宽有限,无法传输该大小的数组,该怎么办? 思路: 通过位图BitMap来压缩数组,将数组中每个数字在bit位上标志,这样就可以将数组大小 ...

  2. BitMap原理

    BitMap原理  

  3. EmguCV从位图(Bitmap)加载Image<Gray,byte>速度慢的问题

    先说背景.最近在用C#+EmguCV(其实就是用P/Invoke封闭了OpecCV,与OpenCVDotNet差不多) 做一个视频的东西.视频是由摄像头采集回来的1f/s,2048X1000大小,其实 ...

  4. 位图索引:原理(BitMap index)

    http://www.cnblogs.com/LBSer/p/3322630.html 位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这 ...

  5. [置顶] 程序员必知(二):位图(bitmap)

    位图是什么? 位图就是数组,一般来说是bit型的数组,具有快速定位某个值的功能,这种思想有很广泛的应用,比如下边两题: 1 找出一个不在5TB个整数中存在的数 假设整数是32位的,总共有4GB个数,我 ...

  6. 布隆过滤BitMap原理

    一.问题引入 BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射,怎么理解呢?举一个例子,有一个无序有界int数组{1,2,5,7},初步估计占用内存44=16字节,这倒是 ...

  7. Android学习之位图BitMap

    BitMap代表一张位图,扩展名可以是.bmp或者.dib.位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2.4.8.16.24和32位色彩.例如 ...

  8. [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法

    1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...

  9. 【索引】位图BitMap索引

    位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...

  10. 位图bitmap应用

    所有比特的编号方法是,从低字节的低位比特位开始,第一个bit为0,最后一个bit为 n-1. 比如说,现在有个数组是这样子的,int a[4],那么a[0]的比特位为0--31a[1]的比特位为32- ...

随机推荐

  1. bugku_EasyMath

    bugku_EasyMath 题目描述 简单的数学题 from Crypto.Util.number import getPrime, bytes_to_long from secret import ...

  2. Java中读取用户输入的是谁?Scanner类

    前言 我们在初学 Java 编程的时候,总是感觉很枯燥乏味,想着做点可以交互的小系统,可以让用户自由输入,系统可以接收做出反映.这就要介绍一下 Java 中的 Scanner 类了. 一.Scanne ...

  3. P8933 [JRKSJ R7] 技巧性的块速递推 题解

    题目传送门 题意: 简单来说就是一个涂色游戏. 有一个 n×m 的棋盘需要涂色. 每格只能涂黑色或白色两种颜色. 横.竖.斜连续 3 格颜色不能相同. 横.竖.斜连续 4 格颜色不能有 3 个相同颜色 ...

  4. 带你体验AI系列之云原生最佳实践--免费体验GPT-4教程

    前言 ​ [GPT-4]是OpenAI最新推出的大型语言模型,它支持图像和文本输入,以文本形式输出.它比GPT-3.5更大.更强.更猛.最重要的是据与研究表明,他在某些场景下,可以通过图灵测试.但是, ...

  5. ASP.NET Core 6框架揭秘实例演示[37]:重定向的N种实现方式

    在HTTP的语义中,重定向一般指的是服务端通过返回一个状态码为3XX的响应促使客户端像另一个地址再次发起请求,本章将此称为"客户端重定向".既然有客户端重定向,自然就有服务端重定向 ...

  6. 记一次 .NET 某埋线管理系统 崩溃分析

    一:背景 1. 讲故事 经常有朋友跟我反馈,说看你的文章就像看天书一样,有没有一些简单入手的dump 让我们先找找感觉,哈哈,今天就给大家带来一篇入门级的案例,这里的入门是从 WinDbg 的角度来阐 ...

  7. UnrecognizedPropertyException: Unrecognized field 解决

    转载请注明出处: 在项目得不同环境上对接外部的服务接口,且存在不同版本间可能有字段不同得问题,遇到这种问题在使用jackson解析时,如果格式化得字符串与定义得java类不能完全对应时,就会报错:Un ...

  8. 曲线艺术编程 coding curves 第十四章 其它曲线(Miscellaneous Curves)

    第十四章 其它曲线(Miscellaneous Curves) 原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ ...

  9. Unity的IPostGenerateGradleAndroidProject:深入解析与实用案例

    Unity IPostGenerateGradleAndroidProject Unity是一款流行的跨平台游戏引擎,它支持多种平台,包括Android.在Unity中,我们可以使用IPostGene ...

  10. 将mongodb注册成windows(win10)的服务

    首先参考这个大佬的文章: 下载mongodb 然后解压 为了方便路径,我改了个名字MongoDB, 然后把它拖到了c盘的Program Files文件夹中 这样他的路径就是 (这个路径在很多地方都要用 ...