android bitmap数据结构,一种很有意思的数据结构:Bitmap

昨晚遇到了一种很有意思的数据结构,Bitmap。

Bitmap,准确来说是基于位的映射。其中每个元素均为布尔型(0 or 1),初始均为 false(0)。位图可以动态地表示由一组无符号整数构成的集合。 每个bit对应一个无符号数。如位图第10个比特为true(1),表示无符号整数9。

之所以用位图来表示整数,是为了 节省 内存。假如要处理50亿个四字节无符号整数,那么需要 5,000,000,000 * 4bytes = 20,000,000,000bytes = (20,000,000,000 / 1024 / 1024 / 1024)GB = 18.63GB 内存,显然普通的计算机无法处理。如果使用位图的话,每个位映射为一个数,则只需要 1bit * 5,000,000,000 = (5,000,000,000 / 8)bytes = (625,000,000 / 1024 / 1024)MB = 596MB,需要的内存降到了 1/32。

如何由一个整数k定位到指定位置?

思路是先定位到第k比特所在的字节位置,然后在计算出它所在这个字节的第几位。

因为一个字节(char)占8位,所以可以由 k >> 3 算出第k比特所在字节位置,这里设找到的这个字节位 b。

然后计算它所在8位字节 b 的第几位,用 k % 8 即可得到,写成位运算 k & 0x07 ,获得低三位所等价的数字,这里设为 x。

定位到了指定位,如何修改它?

已经找到了第k比特在字节 b 的 第 x 位。如果要将k添加进位图,就需要将字节 b 的 第 x 位设置为1,只需用一个第 x 位为1的字节与字节 b 做或运算即可。构造这样的字节:0b1000_0000 >> x(就是:0x80 >> (k & 0x07)),就可以将字节第 x 为设为1。然后通过位运算 | ,M[k >> 3] |= (0x80 >> (k & 0x07))。

完整的 Bitmap C++代码:

//代码来自邓俊辉数据结构习题集

class Bitmap {

private:

char *M; //比特图所存放的空间为M[]

int N; //容量为 N*sizeof(char)*8,就是N*8,一个字节8位

protected:

void init(int n) {

M = new char[N = (n + 7) / 8];

memset(M, 0, N); //将指针M后的N个字节用0代替,初始化位图,位全设置为0

}

public:

Bitmap(int n = 8) { //按指定规模创建比特图

init(n);

}

Bitmap(char* file, int n = 8) { //从文件中读取比特图

init(n);

FILE* fp = fopen(file, "r");

fread(M, sizeof(char), N, fp);

fclose(fp);

}

~Bitmap() { //释放比特图空间

delete[] M;

M = nullptr;

}

void set(int k) { //设置第k个比特为1

expand(k);

M[k >> 3] |= (0x80 >> (k & 0x07));

/*

* 因为每个字节包含8个比特,所以通过位运算 k>>3 可以确定对应的比特所属第几个字节。

* 通过逻辑位与运算 k & 0x07[0b0111] 可以确定比特位所属字节的第几个位。获得k的低3比特,即比特在字节中的位置,设为x。

* 通过移位操作 0x80[128:0b1000_0000] >> (k & 0x07) 可以得到该比特位所在字节中对应的数值的掩码。

* 将(128:0b1000_0000)中最高位的1右移x。即将x位设置为1。然后 |=,将M第k字节的第x为设为1。

*/

}

void clear(int k) { //第k个比特清零

expand(k);

M[k >> 3] &= ~0x80 >> (k & 0x07);

/*

* ~0x08 是 0b01111111,将最高位0右移到第x位,然后 &= 就是设M第k个字节的第x位为0.

*/

}

bool test(int k) { //判断是否存在k

expand(k);

return M[k >> 3] & (0x80 >> (k & 0x07));

/*

* 判断M第k个字节的第x位是否为1

*/

}

void dump(char* file) {

FILE* fp = fopen(file, "w");

fwrite(M, sizeof(char), N, fp);

fclose(fp);

}

char* bits2string(int n) { //将前n位转换为字符串

expand(n - 1); //此时可能被访问的最高位为Bitmap[n-1]

char* s = new char[n + 1];

s[n] = '\0';

for (int i = 0; i < n; i++)

s[i] = test(i) ? '1' : '0';

return s;

}

void expand(int k) { //若被访问的Bitmap[k]已出,则需扩容

if (k < 8 * N) //无需扩容

return;

int oldN = N;

char* oldM = M;

init(2 * k); //加倍扩容

memcpy_s(M, N, oldM, oldN); //原数据转移至新空间

delete[] oldM;

}

};

应用:

可进行数据的快速查找,判重,删除。直接将整数k做位运算即可,复杂度为O(1)。

在不开启事件循环的线程中使用QTimer(QThread&colon;&colon;run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good

引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...

关于Java异常一段很有意思的代码

今天学习了Java的异常,讲到try-catch-finally时,老师演示了一段代码,觉得很有意思,很能反映出其执行的过程,让自己有点绕,特意记录一下. 只要代码执行到try代码内部, 不管有没有异 ...

Gym - 101291C &lpar;很有意思的最短路)

题意: 给出一张地图和机器人还有出口的位置,地图上面有障碍.然后给出UDLR上下左右四种指令,遇到障碍物或者越界的指令会忽略,剩下的继续执行. 只要到达出口就算找到出口,然后给你一串指令,让你修改指令 ...

一行css代码调试中学到的javascript知识,很有意思

现在到处都是JavaScript,每天都能知道点新东西.一旦你入了门,你总能从这里或是那里领悟到很多知识.今天我想分享Addy Osmani的一行代码 ,这行代码对于你调试你的CSS是很有用的.为了可 ...

We7——很有意思的一个开源CMS

目前做门户.做网站,基本上都需要用到一个系统,那就是CMS内容管理系统:现在开源产品有很多,笔者也是从事这个行业的,国内的各大CMS提供商基本上都试用过,今天向大家推荐一款很有意思的产品——We7CM ...

介绍一种很棒的wince 如何替换系统声音的方法

Topic:介绍一种很棒的wince 如何替换系统声音的方法(作者:Baiduluckyboy) //------------------------------------------------- ...

一道很有意思的java线程题

这几天看结城浩的,跟着做一些习题,有几道题目很有意思,记录下自己的体会. 首先是题目(在原书212页,书尾有解答): public class Main { pu ...

&lbrack;Python&rsqb;&lbrack;pythonchallenge&rsqb;&lbrack;TBC&rsqb;古老的python在线挑战赛,很有意思 &lpar;C0-C4&rpar;

预计阅读时间:15分钟 背景:搜索资料时候偶然发现的,很有意思,每一关都覆盖了很多知识点 Python版本:3.0 Talking is cheap,show me the code 主页: http ...

一套很有意思的C语言测试题目

网络上逛博客,发现了一套很有意思的测试题目: https://kobes.ca/ 大家有兴趣可以做一下,考一些关于C语言使用的细节: 中文翻译参考: https://www.cnblogs.com/l ...

随机推荐

块级元素 Vs 内联元素

HTML的元素可以分为两种: 块级元素(block level element ) 内联元素(inline element ) 二者的区别如下: 1. 块级元素独占一行(除非显示修改元素的displa ...

NSDate获取当前时间,并且转化为需要的格式

NSDate *date = [NSDate date]; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; [formatter ...

loj 1004&lpar;dp&rpar;

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25830‘ 思路:类似与数塔问题,自底向上处理,输入的时候稍微注意一 ...

careercup-排序和查找 11&period;3

11.3 给定一个排序后的数组,包含n个整数,但这个数组已被旋转很多次,次数不详.请编写代码找出数组中的某个元素.可以假定数组元素原先是按从小到大的顺序排序的. 解法: 可以直接从开始一个一个比较,也 ...

【思路解析】discuz 帖子设置封面 setthreadcover 表pre&lowbar;forum&lowbar;threadimage

在Discuz 中有一项就是给帖子设置封面,很多情况下只能通过手动的方式去设置或者用提交POST请求的式去设置: 但是这都是调用DISCUZ的功能设置的: 有的时候并非万能的,也有用不到的时候:下面就 ...

【转】2014区域赛小结(牡丹江&amp&semi;&amp&semi;鞍山)by kuangbin

Posted on 2014年10月20日 by kuangbin 最后的两场区域赛结束了! ICPC生涯的最后两场区域赛,选择了前两个赛区——牡丹江和鞍山,主要是时间比较靠前,而且我向来对东北赛区有 ...

SaltStack 安装介绍 01

一.入门指南 1.1 SALTSTACK是什么? The backbone of Salt is the remote execution engine, which creates a high-s ...

Spring Boot入门-快速搭建web项目

Spring Boot 概述: Spring Boot makes it easy to create stand-alone, production-grade Spring based Appli ...

交换排序-C&num;实现

交换排序包括:冒泡排序和快速排序 具体代码如下: 冒泡排序: /// /// 冒泡排序 /// 稳定性:稳定 /// 时间复杂度:O(n2) ///

nio 序列化

1.序列化 public class SerializeUtils { public byte[] serialize(T t) { byt ...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值