【C++】位图

位图

  • 1. 位图
    • 1.1 位图的概念
    • 1.1 位图的实现
    • 1.3 位图的应用
  • 2. 布隆过滤器
    • 2.1 概念
    • 2.2 模拟实现
    • 2.3 优点和缺点
    • 2.4 应用场景
    • 2.5 哈希切分的应用


1. 位图

1.1 位图的概念

位图,就是用二进制位来表示数据的某种状态,例如判断数据是否存在,二进制位为1说明在,二进制位为0说明不在。位图适用于大量无重复的数据。
在这里插入图片描述

1.1 位图的实现

  1. 例子

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。

分析
40亿个整形=160亿个字节≈16G,将16G的数据放到内存,空间显然是不太够的,所以更不用考虑遍历、排序+二分查找、用set存储。既然是判断在不在,就可以不需要存储整形。开2 ^ 32个比特位(2 ^ 29个字节 ≈ 0.5G)标记对应值在不在,在就将该比特位标记为1,不在就将比特位标记为0。

  1. 模拟实现
namespace zn
{//非类型模板参数,将要开的bit位数传过来template<size_t N>class bitset{public://将空间开好,不建议扩容bitset(){//记得向上取整,否则空间开辟不够_v.resize(N / 32 + 1);}//set将n映射的位置置为1void set(size_t n){size_t i = n / 32;//在第i个整形size_t j = n % 32;//在这个整形的第几个位上面//如何将某bit位置1_v[i] |= (1 << j);}//reset将n映射的位置置为0void reset(size_t n){size_t i = n / 32;size_t j = n % 32;//如何将某bit位置0_v[i] &= ~(1 << j);}//判断这个数在不在->判断某bit位为1还是为0bool test(size_t n){size_t i = n / 32;size_t j = n % 32;//其他位都为0,只判断第j位是否为1return _v[i] & (1 << j);}private:vector<int> _v;};
}

1.3 位图的应用

//1. 给定100亿个整数,设计算法找到只出现一次的整数(整形最多只有42亿多个,所以肯定有重复的)?
//法一:用两个bit位记录出现次数:01(一次),10(两次),11(三次),这样一个整形只能标记16个数据出现次数
//法二:开两个位图,对应bit位表示出现次数:01(一次),10(两次),11(三次)
template<size_t N>class twobit{public:void set(size_t N){//00 -> 01if (!_b1.test(N) && !_b2.test()){_b2.set(N);}//01 -> 10else if (!_b1.test(N) && _b2.test(N)){_b1.set(N);_b2.reset(N);}//超过两次的就没必要记录}bool is_once(size_t N){return !_b1.test(N) && _b2.test(N);}private:bitset<N> _b1;bitset<N> _b2;};//2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
//法一:开两个位图,将文件一映射到位图一,将文件二映射到位图二,遍历其中一个文件,如果两个位图对应bit位都为1,说明是交集
//法二:一个文件所有值映射到一个位图,另一个文件判断在不在,出来的交集需要去重 
//3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
//与第一题做法类似,用两个位图表示,找出出现次数为0的和出现次数为1的数目,相加即可。

2. 布隆过滤器

如果文件的内容是字符串,怎么办?可以将字符串转换成整形,然后在位图对应位置置为1。但由于无论怎么转换,总会有相同的整形值,然后发生冲突,导致误判。所以就有布隆过滤器。

2.1 概念

布隆过滤器,是用多个哈希函数,将一个数据映射到位图的多个位置,从而实现降低冲突概率。特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”(判断一个值在可能存在误判,因为其他数据的映射位置可能与该值重叠;判断一个值不在是准确的,通过该值得到的映射位置只要有一个为0,说明该值不在)。
在这里插入图片描述

2.2 模拟实现

#include<bitset>
#include<string>
using namespace std;struct BKDRHash
{size_t operator()(const string& str){size_t hash = 0;for (auto ch : str){hash = hash * 131 + ch;}//cout <<"BKDRHash:" << hash << endl;return hash;}
};struct APHash
{size_t operator()(const string& str){size_t hash = 0;for (size_t i = 0; i < str.size(); i++){size_t ch = str[i];if ((i & 1) == 0){hash ^= ((hash << 7) ^ ch ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}}//cout << "APHash:" << hash << endl;return hash;}
};struct DJBHash
{size_t operator()(const string& str){size_t hash = 5381;for (auto ch : str){hash += (hash << 5) + ch;}//cout << "DJBHash:" << hash << endl;return hash;}
};template<size_t N,class K = string,class HashFunc1 = BKDRHash,class HashFunc2 = APHash,class HashFunc3 = DJBHash>
class BloomFilter
{
public://将三个哈希函数映射的位置置1void Set(const K& key){//HashFunc1()是匿名对象size_t num1 = HashFunc1()(key) % N;size_t num2 = HashFunc2()(key) % N;size_t num3 = HashFunc3()(key) % N;_bs.set(num1);_bs.set(num2);_bs.set(num3);}//查询key是否在布隆过滤器bool Test(const K& key){//只要有一个映射位置为0,说明key不在if (_bs.test(HashFunc1()(key)%N) == false){return false;}if (_bs.test(HashFunc2()(key)%N) == false){return false;}if (_bs.test(HashFunc3()(key)%N) == false){return false;}//即使三个映射位置都为1,也可能存在误判return true;}
private:bitset<N> _bs;
};

注意
布隆过滤器不支持reset,因为可能会影响到其他字符串的映射(将该位置置为0后,其如果其他字符串的映射位置也是该位置,这会影响以后的查找)。如果硬要支持reset,可以用多个比特位标识一个值作为计数,但这就削弱图和布隆的优势,本来就要处理大量数据,现在空间又变少,还有可能引发计数回绕(0减1后会回到该类型的上限,所有比特位为1)。

2.3 优点和缺点

  1. 优点

(1)查询和插入效率非常高,时间复杂度是O(K),K取决于哈希函数的个数。
(2)处理大量数据,特别是字符串。
(3)节省空间,空间利用率高。
(4)使用同一组散列函数的布隆过滤器可以进行交、并、差运算。

  1. 缺点

(1)不能进行删除操作。
(2)可以通过位图判断是否存在,但不能得到元素本身。
(3)存在误判。

2.4 应用场景

// 布隆过滤器的应用
// 题目:给两个文件A和B,分别有100亿个query(查询,每个query所用的字节不一定相同),我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法
// 
// 思路:创建1000个Ai小文件和1000个Bi小文件(i = 0,1,2,……,999),分别从A和B中读取query,通过哈希映射到Ai和Bi文件中,i = HashFunc(query)%1000,i是多少,query就进入第i个小文件。如果Ai和Bi非空,交集就是Ai和Bi。
// 
// 方法:哈希切分:A和B中相同query一定会分别进入Ai和Bi编号相同的小文件。
// 
// 问题:找交集,Ai读出来放到一个set,依次读取Bi的query在不在set中,在就是交集并且删掉。但还有一个问题,此方法是哈希切分不是平均切分,如果冲突太多或者相同的query太多,会导致某个Ai文件太大,甚至超过1G,怎么办?
//
// 解决方案:1.先把Ai的query读到一个set,如果set的insert报错抛异常(bad_alloc),那么说明Ai中
// 大多数query都是冲突的,此时只需换一个HashFunc进行二次切分,再读取Bi的query判断在不在set中,在就是交集。如果Ai中query能够全部读出来,说明Ai中大多数query都是相同的,此时放到set已经去重,再读取Bi的query判断在不在set中,在就是交集。

2.5 哈希切分的应用

// 哈希切分
// 给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
// 思路:进行哈希切分,i = HashFunc(query)%1000,相同ip一定会进入同一个小文件,再用map
// 去分别统计每一个小文件中ip出现次数,就可以得到ip出现次数最多,或者出现次数最多的前K个。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149909.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

教你拥有一个自己的QQ机器人!0基础超详细保姆级教学!基于NoneBot2 Windows端搭建QQ机器人

0.序言 原文链接&#xff1a;教你本地化部署一个QQ机器人本教程主要面向Windows系统用户教程从0开始全程详细指导&#xff0c;0基础萌新请放心食用&#x1f355;如果你遇到了问题&#xff0c;请仔细检查是否哪一步有遗漏。如果你确定自己的操作没问题&#xff0c;可以到原文链…

信看课堂-厘米GNSS定位

我们常常说GPS 定位&#xff0c;不过定位远不止GPS定位&#xff0c;通过本节课程&#xff0c;我们将会了解到&#xff0c;原来GPS只是定位的一种&#xff1a; GNSS概述 不同的GNSS系统使用不同的频段来传输导航信号。以下是一些主要的GNSS系统及其相应的频段&#xff0c;用表…

苹果系统_安装matplotlib__pygame,以pycharm导入模块

为了更便捷、连贯的进行python编程学习&#xff0c;尽量在开始安装python软件时&#xff0c;将编辑器、模块一并安装好&#xff0c;这样能避免以后版本冲突的问题。小白在开始安装pycharm、pip、matplotlib往往会遇到一些问题&#xff0c;文中列示其中部分bug&#xff0c;供大家…

1200*C. Challenging Cliffs(模拟构造贪心)

Problem - 1537C - Codeforces Challenging Cliffs - 洛谷 解析&#xff1a; 排序数组&#xff0c;然后找出间隔最短的两个相邻的数 a&#xff0c;b&#xff0c;c&#xff0c;d&#xff0c;e&#xff0c;f &#xff08;假设b&#xff0c;c为差最小的两个数&#xff09;。 然后…

Python无废话-办公自动化Excel格式美化

设置字体 在使用openpyxl 处理excel 设置格式&#xff0c;需要导入Font类&#xff0c;设置Font初始化参数&#xff0c;常见参数如下&#xff1a; 关键字参数 数据类型 描述 name 字符串 字体名称&#xff0c;如Calibri或Times New Roman size 整型 大小点数 bold …

【一、灵犀考试系统项目设计、框架搭建】

一、创建数据库 1、打开power designer&#xff0c;新建数据库模型 2、新建数据表&#xff0c;以及关系 【注意】 图片的类型有两种&#xff1a;varbinary 和 image varbinary : 二进制字节流&#xff0c;可以自动控制长度 image : 最大可放2G图片 3、创建数据库&#…

创新家庭办公室:打造完美工作空间的秘诀

一个精心策划的家庭办公室有很多好处&#xff0c;何不把临时工作区升级改造为你的专属工作区呢&#xff0c;还能为这些至关重要的区域注入新的活力。 创造多用途的起居室&#xff1a;我们大多数人都不曾拥有一个可以完全根据工作需求设计的独立家庭办公室——所以有时候要找到…

QT:鼠标画线(双画布)

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPoint> //点 #include <QMouseEvent> //鼠标事件 #include <QPaintEvent> //绘图事件class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent 0);~Wi…

【算法训练-贪心算法 一】买卖股票的最佳时机II

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【贪心算法】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

docker系列6:docker安装redis

传送门 docker系列1&#xff1a;docker安装 docker系列2&#xff1a;阿里云镜像加速器 docker系列3&#xff1a;docker镜像基本命令 docker系列4&#xff1a;docker容器基本命令 docker系列5&#xff1a;docker安装nginx Docker安装redis 通过前面4节&#xff0c;对docke…

C#中的数组探究与学习

目录 C#中的数组一般分为:一.数组定义:为什么要使用数组?什么是数组?C#一维数组for和foreach的区别C#多维数组C#锯齿数组初始化的意义:适用场景:C#中的数组一般分为: ​①.一维数组。 ②.多维数组,也叫矩形数组。 ③.锯齿数组,也叫交错数组。 一.数组定义: 数组…

Halcon 从基础到精通-02- 开发基于HALCON的应用

HALCON的应用通过HDevelop应用来构建原型。HDevelop的开发主要有3种形式。 Start from Scratch: 手动通过脚本&#xff0c;把HDevelop的代码转化为一般的编程语言。如&#xff0c;上一节提到&#xff0c;其实&#xff0c;每个operators,也许并不一样&#xff0c;需要依据HALC…

云安全之等级保护解决方案及应用场景

等保2.0解决方案背景 适应云计算、移动互联网、大数据、物联网和工业控制等新技术发展&#xff0c;在新的技术场景能够顺利开展等级保护工作;《网络安全法》2016年已正式发布&#xff0c;等级保护2.0为了更好配合《网络安全法》的实施&#xff1b;等级保护1.0&#xff0c;在适…

(32)测距仪(声纳、激光雷达、深度摄影机)

文章目录 前言 32.1 单向测距仪 32.2 全向性近距离测距仪 32.3 基于视觉的传感器 前言 旋翼飞机/固定翼/无人车支持多种不同的测距仪&#xff0c;包括激光雷达&#xff08;使用激光或红外线光束进行距离测量&#xff09;、360 度激光雷达&#xff08;可探测多个方向的障碍…

SpringBoot自带模板引擎Thymeleaf使用详解①

目录 前言 一、SpringBoot静态资源相关目录 二、变量输出 2.1 在templates目录下创建视图index.html 2.2 创建对应的Controller 2.3 在视图展示model中的值 三、操作字符串和时间 3.1 操作字符串 3.2 操作时间 前言 Thymeleaf是一款用于渲染XML/HTML5内容的模板引擎&am…

【初识Linux】Linux环境配置、Linux的基本指令 一

Linux基本指令一 一、学习前提(环境配置&#xff09;①安装Xshell和云服务器推荐②Xshell用途如下图③打开Xshell 二、 Linux基本指令①whoami和who指令②pwd、ls、ls -l三个指令ls指令扩充 ③cd指令前提了解有了上面的认识&#xff0c;我们就可以开始cd指令的学习了 ④tree指令…

【JavaEE】JUC(Java.util.concurrent)常见类

文章目录 前言ReentrantLock原子类线程池信号量CountDownLatch相关面试题 前言 经过前面文章的学习我们大致了解了如何实现多线程编程和解决多线程编程中遇到的线程不安全问题&#xff0c;java.util.concurrent 是我们多线程编程的一个常用包&#xff0c;那么今天我将为大家分…

ES 关于 remote_cluster 的一记小坑

最近有小伙伴找到我们说 Kibana 上添加不了 Remote Cluster&#xff0c;填完信息点 Save 直接跳回原界面了。具体页面&#xff0c;就和没添加前一样。 我们和小伙伴虽然隔着网线但还是进行了深入、详细的交流&#xff0c;梳理出来了如下信息&#xff1a; 两个集群&#xff1a;…

源码上分析Vue2和Vue3的响应式原理

本文节选自我的博客&#xff1a;源码上分析Vue2和Vue3的响应式原理 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是MilesChen&#xff0c;偏前端的全栈开发者。&#x1f4dd; CSDN主页&#xff1a;爱吃糖的猫&#x1f525;&#x1f4e3; 我的博客&#xff1a;爱吃糖…