上篇我们讲了BitMap是如何对数据进行存储的,没看过的可以看一下【算法与数据结构专场】BitMap算法介绍

这篇我们来讲一下BitMap这个数据结构的代码实现。

回顾下数据的存储原理

一个二进制位对应一个非负数n,如果n存在,则对应的二进制位的值为1,否则为0。

这个时候,我们的第一个问题:

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

在Java的bitMaP实现中,它采用的是用一个long数据来进行存储的。一个long占用8个字节,即64bit,所以一个long可以存储64个数。例如 arr 是一个long 类型的数组,则 arr[0]可以存 0 ~ 63,arr[1]可以存64 ~127,以此类推。

不过,我们就采用byte数组的来存吧。一个byte占用一个字节,即8bit,可以存8个数字。

当然,你要采用long数组来存也可以。在实现上可以说是一样的。

例如我们要存储(1,3,5,7,8,10)时,他们的内存如下所示。

下面我们就来讲讲如何对一个一个位进行操作的。

如何向bitmap中添加一个数值

我们先来说说如何在bitmap中如何添加一个数值的问题,例如我们我们要添加n=14。

这个其实很简单,我们先找到n在arr数组中的下标index,显然index = 1。然后再找到n在arr[index]中的位置position,显然这里position = 6。

这里还是可以很容易找出index和position的公式的。即

index = n / 8 = n >> 3。

position = n % 8 = n & 0x07。

接下来我们把1向右移动position个二进制位,然后把所得的结果和arr[index]做“或(or)”操作就可以了。如下图

这里有个需要注意的地方,在画图的时候,为了方便,我们是把左边的位当作低位,右边的位当作高位来算了。不过在实际的存储中,左边的才是存高位,而右边的存的是低位。所以在我们的代码实现中,我们所说的右移对应代码的左移。

代码实现

//添加数据的操作public void add(int n) {//用<<的操作,运算会比较快。int index = n >> 3;int position = n & 0x07;//把1右移和做or操作两步一起//即<<对应上图的右移,实际上<<是左移符arr[index] |= 1 << position;
}

知道了add操作,其他的操作差不多类似。

当然,我们实现的add操作只是简单的实现一下,假如你要严谨地实现的话,还是需要很多异常的判断的。例如判断这个数是否是非负数,判断arr数组是否下标越界,进行容量的扩充等等。有兴趣的可以严谨去实现一下。

删除操作

我们只需要把对应的二进制的1变成0就可以了。

我们可以把1右移(代码中对应左移)后的结果取反,然后与arr[index]做“与”操作就可以了。代码如下:

public void delete(int n) {int index = n >> 3;int position = n & 0x07;arr[index] &= ~(1 << position);
}

判断是否存在操作

我们把1右移之后,把结果和arr[index]做“与”操作,如何结果不为0,则证明存在,否则就不存在。

public boolean contain(int n) {int index = n >> 3;int position = n & 0x07;return (arr[index] & (1 << position)) != 0;
}

三个最基本的操作代码基本实现了。

希望大家能够去实践一下。

全部代码:

public class BitMap {private byte[] arr;//容量,即最多能够存多少个数据private int capacity;public BitMap(int capacity) {this.capacity = capacity;//一个byte可以存8个数据,capacity实际上指的是多少个bitarr = new byte[(capacity / 8 + 1)];}//添加数据的操作public void add(int n) {//用>>的操作是,运算会比较快int index = n >> 3;int position = n & 0x07;//把1右移和做or操作两步一起//即<<对应上图的右移,实际上<<是左移符arr[index] |= 1 << position;}public void delete(int n) {int index = n >> 3;int position = n & 0x07;arr[index] &= ~(1 << position);}public boolean contain(int n) {int index = n >> 3;int position = n & 0x07;return (arr[index] & (1 << position)) != 0;}
}

问题

大家看了以上的代码,有没发现一些问题呢?

例如我们只在bitmap存储1个数,并且存的数值是2000000000,我们就会在第2000000000个二进制把0改为1。也就是说arr数组的大小至少为2000000000/8+1。可是这时候前面的二进制位并没有存数据,那不是超级超级浪费资源?

所以说,像我们上面的那种写法可以说是暴力写法,没有经过任何优化,实际上,在Java自带的bitMap中是有很多优化的,并不会像我们上面实现的代码一样那么浪费空间资源。有兴趣的可以研究下。

至于如何优化,我会在之后的文章讲,尽情期待。觉得有帮助的话可以转发分享给更多的小伙伴哦

参考链接:https://mp.weixin.qq.com/s?__biz=MzUxNzg0MDc1Mg==&mid=2247484157&idx=1&sn=0826f11852cbfe3043bfac22e4aff27c&chksm=f99348e2cee4c1f48862e5d7536e24f4517f3d88753f452f03a2096ff2e7ab113706b3e54652&scene=21#wechat_redirect

【算法与数据结构专场】BitMap算法基本操作代码实现相关推荐

  1. 《算法与数据结构专场》BitMap算法介绍

    我们先来看个简单的问题. 假如给你20亿个非负数的int型整数,然后再给你一个非负数的int型整数t,让你判断t是否存在于这20亿数种,你会怎么做呢? 有人可能会用一个int数组,然后把20亿个数给存 ...

  2. python算法与数据结构-希尔排序算法

    希尔排序(shell sort)是插入排序的一种,也称缩小增量排序,与普通的插入算法的区别就是gap步长. 希尔排序内层循环逻辑如下所示: 上面的可以分为4组,一个一个的按照插入算法来做,第一组有54 ...

  3. 数据结构与算法专题——第一题 Bitmap算法

    在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在定位查找场景上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场合下: ①:对10亿个不重复的整数进行排序. ②:找出1 ...

  4. 算法与数据结构——位图BitMap

    一.介绍 1.1 什么是位图 在Java中有四种整数类型:byte.short.int.long. 1 byte(字节) = 8 bit(位) 1 int = 4 byte = 32 bit 所以我们 ...

  5. 算法与数据结构(排序算法概述)

    排序算法 Sort Algorithm 排序算法是将一系列数据根据指定的顺序进行排列的过程 排序算法的分类: 内部排序:指将需要处理的所有数据都加载到内存中进行排序 插入排序 直接插入排序 希尔排序 ...

  6. python算法与数据结构-希尔排序算法(35)

    阅读目录 一.希尔排序的介绍 二.希尔排序的原理 三.希尔排序的图解 四.希尔排序的python代码实现 五.希尔排序的C语言实现 六.希尔排序的时间复杂度 七.希尔排序的稳定性 一.希尔排序的介绍 ...

  7. python算法与数据结构-选择排序算法(33)

    阅读目录 一.选择排序的介绍 二.选择排序的原理 三.选择排序的图解 四.选择排序总结 五.选择排序的python代码实现 六.选择排序的C语言代码实现 七.选择排序的时间复杂度 八.选择排序的稳定性 ...

  8. java 线性的排序算法_数据结构之排序算法Java实现(9)—— 线性排序之 基数排序算法...

    基数排序算法是计数排序的延伸,计数排序会造成很大的空间浪费,但基数排序法是对位数进行排序,适合于位数之间相差较大的情况,废话不多说,直接上代码: 升序排序法: /** * 基数排序法 * 升序排列 * ...

  9. 基础算法与数据结构——页面置换算法

    一.引言 第一次接触页面置换算法是在大学里学习<操作系统>时候,起初觉得只是几个简单的算法而已,并没有太多的关注,随着阅历的增长,才发现页面置换算法的思想出现在缓存.分布式.中间件.网络等 ...

最新文章

  1. TIP 2018论文概述:基于深度学习的HEVC复杂度优化
  2. R语言——导入Excel表格数据方法
  3. CodeForces - 76E Points
  4. 深入了解crc32算法
  5. 音视频多媒体协议相关资料汇总
  6. gateway动态路由_无语!SpringCloud Gateway动态路由之Nacos,我已经讲得很清楚了
  7. libcurl overview
  8. 【云图】如何制作中国贪官落马图?
  9. 【java与智能设备】单选框 复选框 监听事件
  10. android图像与动画处理,在Android和iPhone上对照片进行动画处理的7种最佳应用 | MOS86...
  11. 深信服 云桌面 linux,深信服桌面云-深信服桌面云下载 v3.0官方版--pc6下载站
  12. 软考中级网络工程师学习笔记(知识点汇总)详细版本
  13. RAW图片转换JPEG图片工具(免费)
  14. java类private_Java访问类中private属性和方法
  15. 中国天气网免费天气API
  16. 公网访问阿里云RDS云数据库
  17. OpenLayers分屏联动对比
  18. linux vnc登陆,vnc登陆,4个步骤教你vnc登陆Linux
  19. AIS(ACL,IJCAI,SIGIR)(2019)论文报告会,感受大佬的气息...
  20. 惊了 消息中间件合集:MQ(ActiveMQ/RabbitMQ/RocketMQ)+Kafka+笔记

热门文章

  1. AtomicLong和LongAdder的区别
  2. JAVAAPI之STRING类和STRINGBUFER类
  3. hbase建表,删表,修改,查询(get,scan,布隆过滤器)
  4. gradle挂接到构建生命周期(七)
  5. 红黑树(RB-Tree)比AVL强在哪?
  6. PAT甲级 -- 1009 Product of Polynomials (25 分)
  7. 洛谷--P1067 多项式输出
  8. 【千字分析】剑指 Offer 46. 把数字翻译成字符串
  9. 4行代码AC——L1-024 后天(5分)
  10. 天平应什么放置_天平是否应该放干燥剂?