位图BiMap

2023-10-05 20:36
文章标签 位图 bimap

本文主要是介绍位图BiMap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在此记录我学的位图相关知识


是什么


是一种数据结构。也可以认为是一种二进制数组。
一个整型int是32位,用他的二进制能表示0-31这些整数是否出现过。

我们现在看int,要深入到微观去看,即看它的二进制,它有32个bit位

比如现在很多App上每月都有签到活动,一个月签到几次就送大礼包。这个功能我们就可以使用这种思想来实现。

 int calender; 用这一个整型来统计某个月的签到情况。
 

day 表示第几天
签到:即第day天签到了,则
int calender =0; 
calender |= (1 << (day & 31))//day表示第几天public void qiandao(int day){int calender =0;  // 00000000 00000000 00000000 00000000 calender |= (1 << (day & 31));System.out.println(calender);}@Testpublic void t1(){qiandao(2);//结果是 4。// 对应二进制  00000000 00000000 00000000 00000100// 说明第二天签到了}

一个整型数组int[ ] a = new int[32];

每个元素都是32位 ,  32*32= 1024。所以,这个数组能表示0-1023这些整数是否出现过。

相当于连起来了。

同理

一个long 是64位,能表示0-63数字是否出现过。

一个long数组 long[ ] b = new long[32], 32 * 64 = 2048 ,所以,这个数组能表示0-2047这些整数是
否出现过。

每一格子存储64个整数是否存在,a[0]可以表示0-64,a[1]可以表示64-127。返过来

126>>6 = 1(即126/64=1),即126落在a[1]里,又因为126 & 63=62(即126 % 64 = 62),所

以,具体来说是 a[1]的第62位表示126是否存在。

若存在,如何将该位设置为1?

使用 | 运算,即按位或运算。

1L 是long形的数字1,有64位,00000000000........000000001

1L << (126 &63) 然后 | 上a[1]

即 a[1] = a[1] | ( 1L << ( 125 & 63))

简写为 a[ 1 ] |= 1L << ( 125 & 63)

可以把数组每个元素看出一个桶。

把握关键点:添加时:

①确定该数 在数组中的哪个元素中(哪个桶中)--- /操作,用 >> 代替

②确定用 该元素的哪一位表示 ---- % 操作,用 &代替

为什么代替?因为位运算速度飞快

那如何删除呢?也很简单。使用 & ,用0 去和那个bit位进行 & 操作。

代码实现位图

看代码应该比较好懂。就是对二进制、位运算的一种巧妙应用。

public  class BitMap{public long[] bits;public BitMap(int max){//给定最大的数//若max=1,则数组长度得是1.若max=0,数组长度是1.抠边界。// >> 6 等价于 /64,但位运算速度更快bits = new long[(max+64) >> 6];}//num & 63 即num%64,看是该元素的第几位。public void add(int num){//两步:找到数组中对应的元素,然后,将相应位 弄成1. 必须写1L,表示是64位的1。//bits[num >> 6] = bits[num >> 6] | (1L << (num & 63));//简写为//bits[num >> 6 ]是确定在哪个桶里。num & 63 是确定在该桶的哪个位置,让1移动过去对准//每一个桶64位bits[num >> 6] |= (1L << (num & 63));}//删除public void delete(int num){bits[num >> 6] &= ~(1L << (num & 63));}public boolean contains(int num){return (bits[num >> 6] & (1L << (num & 63))) != 0;}
}

   带有测试的

public  class BitMap{public long[] bits;//给定一个预估的最大值,初始化数组,看看最多需要几个格子(几个坑位)//    如果实际业务中,超过了,那就重写造一个public BitMap(int max){//给定最大的数//若max=1,则数组长度得是1.若max=0,数组长度是1.抠边界。//看看最多需要几个格子。 >> 6 等价于 /64,但位运算速度更快bits = new long[(max+64) >> 6];}//num & 63 即num%64,看是该元素的第几位。public void add(int num){//两步:找到数组中对应的元素,然后,将相应位 弄成1. 必须写1L,表示是64位的1。//bits[num >> 6] = bits[num >> 6] | (1L << (num & 63));//简写为//bits[num >> 6 ]是确定在哪个桶里。num & 63 是确定在该桶的哪个位置,让1移动过去对准//把1怼上去//每一个桶64位bits[num >> 6] |= (1L << (num & 63));}//删除 // 这个好理解,就是先非一下,然后和他与,这样可以保证其他位置不变,只变标志位public void delete(int num){bits[num >> 6] &= ~(1L << (num & 63));}public boolean contains(int num){return (bits[num >> 6] & (1L << (num & 63))) != 0;//注意:是!=0, 它的结果不一定全是1}//1L << (num & 63) 相当于一个可以滑动的游标,一个辅助工具。public static void main(String[] args) {System.out.println("测试开始!");int max = 10000;BitMap bitMap = new BitMap(max);HashSet<Integer> set = new HashSet<>();int testTime = 10000000;for (int i = 0; i < testTime; i++) {int num = (int) (Math.random() * (max + 1));double decide = Math.random();if (decide < 0.333) {bitMap.add(num);set.add(num);} else if (decide < 0.666) {bitMap.delete(num);set.remove(num);} else {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");break;}}}for (int num = 0; num <= max; num++) {if (bitMap.contains(num) != set.contains(num)) {System.out.println("Oops!");}}System.out.println("测试结束!");}}

什么用

当最大值确定时,就可以用位图收集数字,表示是否存在。好处是极大省空间。

搞牛逼一点,就是布隆过滤器,布隆过滤器就是使用 位图 + 多个哈希函数 实现的

位运算常识

a << 1 等价于 a*2

a<<2 等价于 a*4

a<<3 等价于 a*8

a<<4 等价于 a*16

a>>1 等价于 a/2

a >> 2 等价于 a/4

a>>3 等价于 a/8

a>> 4 等价于 a/16

a>>5 等价于 a/32

a>>6 等价于 a/64

a%64 等价于 a & 63,

a % n 等价于 a & (n-1),前提是 n必须是 2的k次幂,即n必须是 1、2、4、8、16、32、64、128...这样的数才行。

在JDK8的  HashMap源码里,二次哈希值对数组长度取模,得到索引。也用了这个操作,

hash & (length -1)

位运算的速度很快。

这篇关于位图BiMap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/152000

相关文章

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

做一个用python脚本生成bmp位图的小工具

需求 我有一些用代码生成位图的需求,例如给定一个坐标(x,y),通过一定的逻辑得到对应的颜色值。目的是以这样的方式得到一些用于调试的位图。 实现这个目的有多种方法,不过我最大的期望是—— “易用性” :我希望当我想生成一个位图时,所做的操作达到最小。这意味着: 首先,这个“工具”不是一个纯C++的工程,否则我每次想生成新位图时,都需要打开我的工程,修改代码后,重新编译。换句话说,生成图片的逻

位运算专题——常见位运算位图的使用力扣实战应用

目录 1、常见位运算 2、算法应用【leetcode】 2.1 判断字符是否唯一【面试题 】  2.1.1 算法思想【位图】  2.1.2 算法代码 2.2 只出现一次的数字 III 2.2.1 算法思想 2.2.2 算法代码 2.3 丢失的数字 2.3.1 算法思想 2.3.2 算法代码 2.4 两整数之和 2.4.1 算法思想 2.4.2 算法代码 2.5 只出现

【数据结构取经之路】位图全解

目录 前言 C++标准库里的位图 位图的设计及实现 位图几个关键接口的实现 set() reset() test()  完整代码 位图的使用场景 位图的优缺点 位图的使用演示 —— 几道面试题的讲解 前言 位图(Bitmap)是一种非常高效的数据结构,主要用于处理大量数据的快速查找、去重等操作。它利用每一位(bit)来表示某个元素是否存在或某种状态,从而极大地

位图读、写、显示的C++实现实例

对图像进行处理的前提是,要能实现对象的打开保存和显示,这是处理的前提。以下在VS2010中基于MFC的框架实现对位图文件的打开、保存和显示功能。 第一步:打开MFC应用程序向导,创建一个单文档的MFC应用程序,向导中的其它参数均可保持默认。 第二部:实现读写和显示功能: 1.打开类视图,为CBMPTestView类添加以下5个函数,方法是右击CBMPTestView,在弹出的菜单中选择添加-

MFC添加的位图不清晰解决办法

pDC->SetStretchBltMode(HALFTONE);//设置拉伸模式后,肯定可以解决失真的现象,没解决说明这个函数没起作用; pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &m_DC, \      0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight, SRCCOP

BMP位图原理深度解析及编程实现RGB565图片格式转换

1、前言         在Windows的画图软件中可以看到,常见的BMP有如下图所示的几种:单色位图、16色位图、256色位图和24位位图,其颜色深度分别为1、4、8、24。         在一些单片机设备中的LCD显示屏幕中,仅仅支持RGB565这一类的16位颜色深度图像,否则图片显示会有异常。但是在Windows中,并没有直接提供16位颜色深度的BMP图片,需要通过特殊的方式去生

redis | 认识非关系数据库Redis的位图数据类型

Redis 非关 kv型 位图常用命令应用场景python操作位图 位图 位图不是真正的数据类型,它是定义在字符串类型中 01100001 97 61 a 01100010 98 62 b 一个字符串类型的值最多能存储512M字节的内容 位上限:2^32 常用命令 SETBIT \x : 16进制 没有key值 GETBIT命令

SpringBoot依赖之Spring Data Redis实现位图Bitmap

Spring Boot 项目中使用 Spring Data Redis 实现位图Bitmap 暂未发表,记录于20240820 概念 Spring Data Redis (Access+Driver) 依赖名称: Spring Data Redis (Access+Driver)功能描述: Advanced and thread-safe Java Redis client for

位图与布隆过滤器 —— 海量数据处理

🌈 个人主页:Zfox_ 🔥 系列专栏:C++从入门到精通 目录 🚀 位图 一: 🔥 位图概念 二: 🔥 位图的实现思路及代码实现三: 🔥 位图的应用四: 🔥 STL中的 bitset 🚀 布隆过滤器 一: 🔥 布隆过滤器提出 二: 🔥 布隆过滤器概念 三: 🔥 布隆过滤器的误判率推导四: 🔥 布隆过滤器的实现五: 🔥 布隆过滤器的删除六: 🔥 布