位图bitmap应用
所有比特的编号方法是,从低字节的低位比特位开始,第一个bit为0,最后一个bit为 n-1。
比如说,现在有个数组是这样子的,int a[4],那么
a[0]的比特位为0——31
a[1]的比特位为32——63
a[2]的比特位为64——95
a[3]的比特位为96——127
现在,我们根据下面这个程序来研究这个数组比特位的编号
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int a[4];
for(int i=0;i<4;i++)
{
a[i]=1;
}
for(i=0;i<4;i++)
{
a[i]=a[i]<<4;
cout<<a[i]<<endl;
}
return 0;
}
结果是输出了4个16,也就是说,一开始的比特位是这样编排的00000000 00000000 00000000 00000001,在使用了位运算(向左移4位)之后成了这样00000000 00000000 00000000 00010000,很明显嘛,这比较符合我们的思维,但是这样子整个数组组织起来就相对比较麻烦咯,具体如下
0……………………0 0……………………0 0……………………0 0……………………0
a[0] 31~~0 a[1] 63~~32 a[2] 95~~64 a[3] 127~~96
//0……………………0 表示32位
利用位运算&实现取模运算%
位运算跟取模运算之间有着微妙的联系,确实很微妙,因为只有在某些特定的情况下才能使用位运算实现
先看个例子,100%32,100&31,经过计算,你会发现结果是一样的,那什么时候才会成立呢?这种计算对前一个数没有要求,不过对后一个的要求比较高,看一看32和31的二进制(统一用八位)表示,32=0010 0000,31=0001 1111,也就是说利用要利用这种算法,后一个数必须满足这样的条件,在取模运算中,该数的二进制表示只能有一位是1,也就是说,这个数必须是2的N次幂;在进行位运算的时候则取该数的前一个数的二进制表示来进行。
设置特定的位,清除特定的位
假如现在有个int类型的整数,i=0,将第5位置为1(写成二进制的时候,从右边数过来的第五位),假设本来都是零
i=i|(1<<5)
例子源码
#include <iostream>
using namespace std;
static int a=0;
void SetBit(int bit)
{
a|=(1<<bit);
}
void ClearBit(int bit)
{
a&=~(1<<bit);
}
int main(int argc, char* argv[])
{
SetBit(5);
cout<<a<<endl;
ClearBit(5);
cout<<a<<endl;
return 0;
}
两个主要的运算:
字节位置=数据/32;(采用位运算即右移5位)
位位置=数据%32;(采用位运算即跟0X1F进行与操作)。
再来个例子,比如说现在我们有100这个数,于是,我们要将第100位置为1,也就是说,我们最少得有100位,100位等于12.5字节,因为一个int型是4个字节,所以我们必须定义一个这样的数组int[4],数组的位模型可以参考上面。现在,我们要对这个数组的100位进行置位操作嘛,那首先我得先知道100是在这个数组中的第几个元素嘛,所以,使用100/32,我现在要第100位,然后,每个数组元素是32位,进行运算之后,我就得到了我要置的位在那一个元素了,那确定了元素之后,我得知道,我要置位的是元素的哪一个位嘛,所以我就得知道求余的结果咯(纯粹数学知识的),所以就100%32咯,然后根据我上面的分析,模运算%与位运算&之间的一个微妙关系,那么我就可以采用这样的运算方式100&0x1F(0x1F是其实就是32),得到要置位的位置了。
给40亿个不重复的unsigned int的整数,没有排过序,然后再给一个数,如果快速判断这个数是否在那40亿个数当中。
因为unsigned int数据的最大范围在在40亿左右(需要40亿bit),40*10^8/1024*1024*8=476,因此只需申请512M的内存空间,每个bit位表示一个unsigned int。读入40亿个数,并设置相应的bit位为1.然后读取要查询的数,查看该bit是否为1,是1则存在,否则不存在。
现在我们把这道题目简化一下(40亿数据太大了。。。不想读文件,不想自己来产生这些数据。。)
///////////例子,包括算法实现(C语言实现,C++的话实在是太方便了,因为有bitset这个东西,所以C++的实现就没写下来)
假如有近100个不重复的正整数,范围在[1-100]之间,但是现在缺失了一些数,要确定缺失的数据。
因为是100个数,所以需要100位,100位=12.5字节,一个int类型是4字节,所以需要4个int类型,因此可以申请一个int数组,数组的大小为4,下面是程序源码。
#include <iostream>
using namespace std;
void SetBit(int bit)
{
a|=(1<<bit);
}
void ClearBit(int bit)
{
a&=~(1<<bit);
}
void SetBit(int n,int *bit) //将逻辑位置为n的二进制位置为1
{
bit[n>>5] |= (1<<((n&0x1F)-1)); //n>>SHIFT右移5位相当于除以32求算字节位置,n&0x1F相当于对32取余即求位位置。
}
void ClearBit(int n,int *bit)//将逻辑位置为n的二进制位置0
{
bit[n>>5] &= ~(1<<((n&0x1F)-1)); //将逻辑位置为n的二进制位置0,原理同set操作
}
int TestBit(int n,int *bit)
{
return bit[n>>5] & (1<<((n&0x1F)-1)); //测试逻辑位置为n的二进制位是否为1,如果为1,则返回非零值,注意,不是返回1,是返回非零值;如果为0,则返回0
}
int main(int argc, char* argv[])
{
int a[100]={11,21,31,41,51,61,71,81,91,
2,12,22,32,42,52,62,72,82,92,
3,13,23,33,43,53,63,73,83,93,
4,14,24,34,44,54,64,74,84,94,
5,15,25,35,45,55,65,75,85,95,
6,16,36,56,66,76,86,96,
7,17,27,37,47,57,67,77,87,97,
8,18,28,38,48,58,68,78,88,98,
9,19,29,39,49,59,69,79,89,99,
10,100};
int bit[4];
int i;
for(i=0;i<4;i++)//将所以的比特位均置0
{
bit[i]=0;
}
for(i=0;i<100;i++)//根据数组里面的数据,将相应的比特位置为1
{
SetBit(a[i],bit);
}
for(i=1;i<=100;i++)
{
if(TestBit(i,bit)==0)
{
cout<<i<<" is not exist"<<endl;
}
else
{
cout<<i<<" is exist"<<endl;
}
}
return 0;
}
对于SetBit和ClearBit两个函数,或许有人会有些疑问
主要是(n&0x1F)-1这个式子,估计有人会有些疑问,因为跟编程珠玑里面有些出入,因为1<<((n&0x1F)-1),很明显,如果没有进行移位的话,很显然,第一位已经是1了,举个例子,我们可以考虑下n为1的那种情况,很显然,这个时候没必要进行移位,直接bit[n>>5] |= 1就得到结果了,如果1<<(n&0x1F)的话,很显然,待会是将第二位置为1,所以这也就是(n&0x1F)-1)后面要减1的原因。
位图bitmap应用的更多相关文章
- (算法)位图BitMap
题目: 给定一数组,大小为M,数组中的数字范围为1-N,如果某带宽有限,无法传输该大小的数组,该怎么办? 思路: 通过位图BitMap来压缩数组,将数组中每个数字在bit位上标志,这样就可以将数组大小 ...
- EmguCV从位图(Bitmap)加载Image<Gray,byte>速度慢的问题
先说背景.最近在用C#+EmguCV(其实就是用P/Invoke封闭了OpecCV,与OpenCVDotNet差不多) 做一个视频的东西.视频是由摄像头采集回来的1f/s,2048X1000大小,其实 ...
- [置顶] 程序员必知(二):位图(bitmap)
位图是什么? 位图就是数组,一般来说是bit型的数组,具有快速定位某个值的功能,这种思想有很广泛的应用,比如下边两题: 1 找出一个不在5TB个整数中存在的数 假设整数是32位的,总共有4GB个数,我 ...
- Android学习之位图BitMap
BitMap代表一张位图,扩展名可以是.bmp或者.dib.位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2.4.8.16.24和32位色彩.例如 ...
- [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法
1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...
- 【索引】位图BitMap索引
位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...
- redis位图(bitmap)常用命令的解析
描述 bitmap是redis封装的用于针对位(bit)的操作,其特点是计算效率高,占用空间少,常被用来统计用户签到.登录等场景 常用命令及解析 常用命令 setbit key offset va ...
- As3.0中的位图(Bitmap/BitmapData)编程
https://blog.csdn.net/wtuetnsrmh/article/details/12577929
- 使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
在 WPF 中将一个现成的 Bitmap 位图转换成 ImageSource 用于显示一个麻烦的事儿,因为 WPF 并没有提供多少可以转过来的方法.不过产生 Bitmap 来源却非常多,比如屏幕截图. ...
随机推荐
- day53 Pyhton 前端04
内容回顾: 盒子: 内边距:padding,解决内部矛盾,内边距的增加整个盒子也会增加 外边距:margin,解决外部矛盾,当来盒子都有外边距的时候,取两者最大值 边框:border border-c ...
- JS关闭chorme页面
百度到的很多答案都失效了,这是收集一位博主的(https://www.jianshu.com/p/9dc2752194b8),目前可以使用. 代价是打开一个空白页面,能实现无提示关闭当前页面.不需要是 ...
- python接口测试之日志功能
之前在简书中看了一篇关于日志功能的文档,供大家参考:https://www.jianshu.com/p/62f7b49b41e7 Python通过logging模块提供日志功能,所以直接导入即可 im ...
- linux-查看内核
[root@localhost vagrant]# uname -r 3.10.0-1127.19.1.el7.x86_64 [root@localhost vagrant]# cat /etc/ ...
- df du linux空间清理,查看文件大小
df -h ,这个命令用于查看服务器空间,运行后的效果图如下: [root@localhost /]# df -h Filesystem Size Used Avail Use% Mounted on ...
- Go go.mod入门
什么是go.mod? Go.mod是Golang1.11版本新引入的官方包管理工具用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理. Go.mod其实就是一个Modules,关于Modu ...
- centos8平台:用fontconfig安装及管理字体(fc-list/fc-match/fc-cache)
一,fc-list所属的rpm包 [root@blog ~]$ whereis fc-list fc-list: /usr/bin/fc-list /usr/share/man/man1/fc-lis ...
- 蒲公英 · JELLY技术周刊 Vol.26: 请问您这个月要来点肝么?
蒲公英 · JELLY技术周刊 Vol.26 今年的十月,不知道大家在 TODO List 上新增了多少条目准备尝鲜,你可能已经准备了 Vue3.Webpack5 以及 React v17.0 RC, ...
- springboot入门系列(二):SpringBoot整合Swagger
上一篇<简单搭建SpringBoot项目>讲了简单的搭建SpringBoot 项目,而 SpringBoot 和 Swagger-ui 搭配在持续交付的前后端开发中意义重大,Swagger ...
- cgdb安装
cgdb官网:http://cgdb.github.io/ 一.cgdb安装 可使用wget命令下载,wget http://cgdb.me/files/cgdb-0.7.0.tar.gz 之后解压 ...