当前位置: 首页 > news >正文

C++---位图

一、基本原理

位图(Bitmap)是一种高效的数据结构,主要用于快速判断某个元素是否存在(通常是整数),其核心原理是通过二进制位(bit) 来表示数据的状态,具有空间效率极高的特点。

  1. 核心思想用一个二进制位(0 或 1)来标记一个整数的存在状态:

    • 位值为 1 表示该整数存在
    • 位值为 0 表示该整数不存在
  2. 空间映射假设要表示范围为 0~N 的整数集合,位图需要的空间仅为 N/8 字节(或 N/32 个 32 位整数)。例如:

    • 表示 0~1023 的整数,只需 1024 bits = 128 bytes(仅 128 字节)。
    • 映射关系:整数 x 对应二进制位的位置为 x,通过 x / 32 定位到数组下标,x % 32 定位到具体位。
  3. 操作逻辑通过位运算实现高效的增删查:

    • 设置存在(set)_bs[i] |= (1 << j)(将第 j 位设为 1)
    • 判断存在(test)return _bs[i] & (1 << j)(非零则存在)
    • 清除存在(reset)_bs[i] &= ~(1 << j)(将第 j 位设为 0)

二、相关接口

1.set

功能:将指定整数 x 对应的二进制位标记为 1(表示 x 存在)。

实现:1 << j 表示将数字 1 向左移动 j 位,得到一个只有第 j 位为 1、其他位都为 0 的二进制数

  • 只会将 _bs[i] 中第 j 位设置为 1(如果原本是 0 的话)
  • 其他位的值会保持不变
void set(size_t x)
{size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);
}

2.reset

功能:将指定整数 x 对应的二进制位标记为 0(表示 x 不存在)。

实现:1 << j 生成一个只有第 j 位为 1、其他位为 0 的二进制数

·~(1 << j) 对上面的结果进行按位取反,得到一个只有第 j 位为 0、其他位全为 1 的二进制数

·_bs[i] & (~(1 << j)) 进行按位与运算,再通过 &= 赋值给 _bs[i]

void reset(size_t x)
{size_t i = x / 32;size_t j = x % 32;_bs[i] &= (~(1 << j));
}

3.test

功能:将指定整数 x 对应的二进制位标记为 0(表示 x 不存在)。

实现:通过 _bs[i] & (1 << j) 运算,若结果非零则返回 true,否则返回 false

bool test(size_t x)
{size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);
}

4.clear

功能:将位图中所有位重置为 0,即清空所有元素。

实现:遍历底层数组,将每个元素赋值为 0

void clear()
{for (int i = 0; i < _bs.size(); i++){_bs[i] = 0;}
}

5.count

功能:计算位图中值为 1 的位的总数(即存在的元素总数)。

实现:遍历数组,对每个元素统计二进制中 1 的个数(可借助快速位计数算法,如 Brian Kernighan 算法)。

6.isEmpty

功能:判断位图中是否没有任何元素(所有位均为 0)。

实现:遍历数组,若所有元素均为 0 则返回 true

三、优缺点

1.优点

  • 空间效率极高(比哈希表节省成百上千倍空间)
  • 操作速度快(基于位运算,CPU 支持高效处理)

2.缺点

  • 仅适用于整数类型
  • 不适用于范围极大的场景(如 0~10^18 会占用过多空间

四、例题

给定100亿个整数,设计算法找到只出现一次的整数

一个文件有100亿个整数,1G内存,设计算法找到出现次数不超过两次的所有整数

思路:

1.状态编码设计

用两个位图 _bs1 和 _bs2 中对应位置的两个二进制位,共同表示一个整数的出现次数:

  • _bs1 的位为高位,_bs2 的位为低位,组合成 2 位状态:
    • 00_bs1=0 且 _bs2=0):该整数出现 0 次
    • 01_bs1=0 且 _bs2=1):该整数出现 1 次
    • 10_bs1=1 且 _bs2=0):该整数出现 2 次
    • 11_bs1=1 且 _bs2=1):该整数出现 3 次及以上(不再区分具体次数)

2.技术更新逻辑

每次遇到一个整数 x 时,根据当前状态更新为下一个状态:

  • 从 00(未出现)→ 01(出现 1 次):仅设置 _bs2 的位为 1
  • 从 01(出现 1 次)→ 10(出现 2 次):设置 _bs1 的位为 1,同时清除 _bs2 的位
  • 从 10(出现 2 次)→ 11(出现 3 次及以上):设置 _bs2 的位为 1(此时 _bs1 已为 1)
  • 达到 11 后不再变化(无论再出现多少次都保持该状态)

3.结果查询

通过读取两个位图对应位置的状态,返回该整数的出现次数类型:

  • 返回 1 时,即为 “只出现一次的整数”,正是问题需要的结果

五、代码展示

#pragma once
#include<vector>
namespace Z
{template<size_t N>class bitset{public:bitset(){_bs.resize(N / 32 + 1);}//x映射的位标记成1void set(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);}//x映射的位标记成0void reset(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] &= (~(1 << j));}//判断是一还是零bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);}void clear(){for (int i = 0; i < _bs.size(); i++){_bs[i] = 0;}}private:std::vector<int> _bs;};template<size_t N>class twobitset{public:void set(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2)// 00->01{_bs2.set(x);}else if (!bit1 && bit2)// 01->10{_bs1.set(x);_bs2.reset(x);}else if (bit1 && !bit2)// 10->11{_bs2.set(x);}}//返回0 出现0次//返回1 出现1次//返回2 出现2次//返回3 出现3次及以上int get_count(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2){return 0;}else if (!bit1 && bit2){return 1;}else if (bit1 && !bit2){return 2;}elsereturn 3;}private:bitset<N> _bs1;bitset<N> _bs2;};
}void test_twobitset()
{Z::twobitset<100> tbs;int a[] = { 12,5,28,18,7,12,23,0,9,28,15,30,7,19,0,25,18,6,23,11 };for (auto e : a){tbs.set(e);}for (size_t i = 0; i < 100; i++){//cout << i << "->" << tbs.get_count(i) << endl;if (tbs.get_count(i) == 1)cout << i <<endl;}
}

http://www.dtcms.com/a/450844.html

相关文章:

  • 杭州网站制作方法扬州广陵区城乡建设局网站
  • 个人印章在线制作网站囧猴wordpress主题
  • wordpress支持php7吗网站如何优化排名
  • 基于Kruise Rollout的全自动流量切换
  • 建设内部网站目的信息网站制作
  • 贵港网站推广商城网站开发多久
  • 企业网站开发报价形式设计师网站大全
  • 企业推广网站无锡网站公司哪家好
  • 优设设计网站导航页面设计分析
  • 上上海网站建设设计wordpress留言表单
  • 5ucms怎样做网站自适应网站建设与网络推广
  • Hexo博客搭建系列(二):主题页面配置
  • Matplotlib 网格线
  • 做淘宝客网站要多少钱平度市建设部网站
  • 网站自动抢注建设网站基础知识
  • 网站推广计划的内容重庆教育建设有限公司网站首页
  • 在哪个网站做跨境电商网站建设服务网络服务
  • php学校网站模板网络科技公司经营范围参考
  • 珠海 网站建设和推广网站服务器位置查询
  • 聊城网站百度推广如何在网站页面添加代码
  • 哪个网站可以做代练网页制作图片
  • 新网站建设银行提升转账额度wordpress 飞龙博客 许愿墙
  • 90后做网站赚了网站建设的教学设计
  • ps做网站尺寸多少像素wordpress后台登陆界面
  • asp网站防注入代码wordpress装百度统计
  • 百度不收录的网站手机怎么自己制作图片
  • 哪里有人收费做网站公司网站设计要求
  • 做网站最清晰的字体网站基本要素
  • 编写网站程序建立网站赚钱
  • Java进阶教程,全面剖析Java多线程编程,线程池,笔记19