【C++修炼之路】24.哈希应用--位图
每一个不曾起舞的日子都是对生命的辜负
哈希应用--位图
- 哈希应用:位图
- 一.提出问题
- 二.位图概念
- 三.位图代码
- 四.位图应用
- 五.经典问题
哈希应用:位图
一.提出问题
问题: 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】
先考虑内存的问题:40亿个整数, 每个整数4字节,换算大约16G的空间,寻常的查找算法都是不可能完成的。因此引入位图。
二.位图概念
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。
通过这种同样是哈希的思想,就可以极大的节省空间,整形范围在0~232-1,因此我们可以开232个比特位,换算下来只有512M的大小,通过直接映射就能够判断。
我们无法开这么大的数组,但我们采用的是bit位的标记,即值是几,就把第几个位标记成1。
那么如何去找呢?实际上我们把数组的元素类型规定为char(int也可以),这样就可以通过如下的方式去找任意一个数:x
-
x映射的值,在第几个char对象上:x/8
-
x映射的值,在这个char对象的第几个比特位:x%8
比特位顺序问题:
事实上,比特位的顺序与机器的大小端无关,仍是和地址一样从右到左:
因此在处理定位x在指定char的第几个比特位上时,就需要从右到左去查找。
三.位图代码
对于位图的功能,要有插入,删除,检测在不在三个功能,如果这样赋值:
size_t i = x / 8;
size_t j = x % 8;
插入就可以这样:_bits[i] |= (1 << j);
删除就可以这样:_bits[i] &= (~(1 << j));
测试这个值在不在就可以这样:return _bits[i] & (1 << j);
此外,一开始同样需要开辟指定大小的空间,因此构造函数中要写出来。
template<size_t N>
class cfy_set
{
public:void set(size_t x)//标记{size_t i = x / 8;size_t j = x % 8;_bits[i] |= (1 << j);}void reset(size_t x)//清除{_bits[i] &= (~(1 << j));}bool test(size_t x)//测试这个值在不在{size_t i = x / 8;size_t j = x % 8;return _bits[i] & (1 << j);}
private:vector<char> _bits;
};
对于测试这个值在不在的返回值,会发生整形提升,因为bool属于int类型,按照符号位的数值进行补位,但是对于逻辑来说不重要。
需要注意的是,由于是无符号数,事实上可以将x/8+1换成(x>>3)+ 1;由于>>的优先级低于+,所以需要加上括号。
测试:
void test_cfy_set()
{//cfy_set<100> cs1;//cfy_set<-1> cs2;//无符号最大数直接传-1,会转成最大数量cfy_set<0xffffffff> cs3;//同上cs3.set(10);cs3.set(10000);cs3.set(8888);cout << cs3.test(10) << endl;cout << cs3.test(10000) << endl;cout << cs3.test(8888) << endl;cout << cs3.test(8887) << endl;cout << cs3.test(9999) << endl;
}
事实上,库中也有位图结构 bitset ,也可以直接通过库中的位图查找。
四.位图应用
一. 给定100亿个整数,设计算法找到只出现一次的整数?
对于此整数有三种状态:
- 出现0次
- 出现1次
- 出现一次以上
因此,我们可以通过两个比特位来标记:00代表出现0次;01代表出现1次,其他的代表出现一次以上。(两个标记位可以表示从1到3)那么位图会变成这样:
此方式虽然可行,但需要第上述代码做出很大变动。那么我们可以采用另一种方式代表两个比特位,即以开两个位图的方式,每个位图的一个比特位组合成两个比特位进行标记:
因此,通过这种方式及思想我们甚至可以给任意范围的数字进行标记。那么接下来就实现一下:
template<size_t N>
class twobitset
{
public:void set(size_t x)//标记{if (!_bs1.test(x) && !_bs2.test(x))// 00{//需要变10_bs2.set(x);}else if (!_bs1.test(x) && _bs2.test(x))//10{_bs1.set(x);_bs2.reset(x);//10}//10不变 }void PrintOnce(){for (size_t i = 0; i < N; ++i){if (!_bs1.test(i) && _bs2.test(i)){cout << i << endl;}}cout << endl;}
private:bitset<N> _bs1;//库里的bitset,当然自己写的也可bitset<N> _bs2;
};void test_twobitset()
{twobitset<100> tbs;int a[] = { 3, 5, 6, 7, 8, 9 ,33, 55, 67, 3,3,3,5,9,33 };for (auto e : a){tbs.set(e);}tbs.PrintOnce();
}
这样就完美的解决了这个问题。
二. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
毫无疑问,位图很容易解决
将每个文件种的数都用位图标记,取位图的交集就可以找到文件的交集。
实际上使用位图就是为了去重,如果直接将一个文件的一部分去遍历另一个文件,虽然可以确定,但是难免一个文件中不会出现重复数据,所以使用位图。
三. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
同样的,和第一题的思路相同,并且也是开两个位图进行处理:
- 00->0次
- 01->1次
- 10->两次
- 3次及以上
以位图的方式就可以减少空间的占用。
五.经典问题
给一个超过100G大小的log file,log中存放着ip地址,设计算法找到出现次数最多的ip地址。
用map显然是不行的,因为内存过大。位图同样不适用,因为找到出现次数最多的ip地址属于<key, value>的问题,而位图的功能是找在或者不在的问题,以及出现的次数是确定的问题,属于<Key, Key>,所以与位图无关。
100个G显然放不进内存。因此我们要考虑将100G的文件细分成小文件,但是直接细分会导致统计不全,所以采用哈希切分的方式将HashFunc(ip)%100分成100个小的Ai号文件,如果这个小文件超过1G,此时就会出现两种情况:
- 这个小文件冲突的ip很多,都是不同的Ip,,大多是不重复的,map统计不下。
- 这个小文件冲突的ip很多,都是相同的ip,map可以统计。
直接用map统计,如果是情况2,是可以统计的,不会报错。如果是第一种情况,map会在insert时报错,这是因为New结点失败,失败会抛异常,因此对于第一种情况我们还需要继续通过不同的HashFunc进行切分,直到满足条件为止。
相关文章:

【C++修炼之路】24.哈希应用--位图
每一个不曾起舞的日子都是对生命的辜负 哈希应用--位图哈希应用:位图一.提出问题二.位图概念三.位图代码四.位图应用五.经典问题哈希应用:位图 一.提出问题 问题: 给40亿个不重复的无符号整数,没排过序。给一个无符号整数&#x…...

4. 字符设备驱动高级--- 下篇
文章目录一、字符设备驱动高级1.1 注册字符设备驱动新接口1.1.1 新接口与旧接口1.1.2 cdev介绍1.1.3 设备号1.1.4 编程实践1.1.5 alloc_chrdev_region自动分配设备号1.1.6 中途出错的倒影式错误处理方法二、字符设备驱动注册代码分析2.1 旧接口register_chrdev2.2 新接口regist…...

ChatGPT介绍以及一些使用案例
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
PCL 点云高斯混合聚类(GMM)
文章目录 一、简介二、算法实现三、实现效果参考资料一、简介 与k均值使用原型向量来刻画聚类结构不同,高斯混合聚类(Mixture-of-Gaussian)采用了概率模型来表达聚类原型。从名字中就可以知晓,该方法将会结合高斯分布来进行聚类过程,该分布的概率密度函数定义如下所示: p (…...
Docker学习(十六)踩坑,如何将对容器的修改同步到基础镜像中
目录1.背景2.解决方法1)将容器文件进行归档2)创建一个新的 Dockerfile3)构建新的基础镜像3.注意事项4.commit命令踩坑记录1.背景 最近接手了一个docker服务,现需要对镜像进行修改,原始的 Dockerfile 已经丢失ÿ…...

食品与疾病关系预测赛题
和鲸平台数据分析实战 题目:食品与疾病关系预测算法赛道 一、赛题描述 食品与疾病关系预测算法赛道 越来越多的证据表明,食物分子与慢性疾病之间存在关联甚至治疗关系。营养成分可能直接或间接地作用于人类基因组,并调节参与疾病风险和疾病…...
Symbol
Symbol是ES6新增的一种基本数据类型 它用来表示独一无二的值, 通过Symbol函数生成 Symbol前面不能加new ,创建symbol类型指的时候传入一个参数,这个参数需要是字符串 使用Symbol函数创建一个symbol类型值,可以给它传入一个字符串参数…...
NC65 对上年度反结账,调整数据后重新结账后,对本年度年初重算时系统报错:更新记数错误。
1、对上年度反结账,调整数据后重新结账后,对本年度年初重算时系统报错:更新记数错误。 解决方案: 1、在期初余额节点,按Ctrl+ALT+A重建期初凭证; 2、到结账节点,重建余额表,选择有问题的财务核算账簿,注意:会计期间要放空; 3、到期初余额节点,将刚才删除期初数据的…...

位运算相关
文章目录一、求1的个数二、另类加法三、数组中出现一次的数字四、数组中出现一次的数字变形一、求1的个数 二进制中1的个数 法一:逐位判断 根据与&运算 n&10,说明n的最右边一位为0 n&11,说明n的最右边一位为1 所以思路就是&…...

Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号
首先区分一下Linux信号跟进程间通信中的信号量,它们的关系就犹如老婆跟老婆饼一样,没有一毛钱的关系。 信号的概念 信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断。比如:红绿灯是一种信号,…...
锯齿数组 - 贪心
文章目录锯齿数组 -贪心(不过挺像滑动窗口的)1144. 递减元素使数组呈锯齿状锯齿数组 -贪心(不过挺像滑动窗口的) 1144. 递减元素使数组呈锯齿状 题目链接:1144. 递减元素使数组呈锯齿状 题目大意:给你一个…...
[CVPR 2022] Balanced Contrastive Learning for Long-Tailed Visual Recognition
Contents IntroductionMethodPreliminariesBalanced Contrastive Learning (BCL)Drawbacks of SCLClass-averagingClass-complementLower bound of BCLOptimization with Logit CompensationFrameworkExperimentReferencesIntroduction 作者发现对于在长尾数据集上,Supervised…...
23种设计模式-工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,而无需将具体的对象创建逻辑暴露给客户端。在Java中,工厂模式常常用于创建复杂对象或对象的构造过程涉及到多个步骤的情况。 在Android开发中,工厂模式也经常被使用&am…...

Linux操作系统学习(进程等待)
文章目录进程等待进程等待的必要性如何进程等待waiwaitpid验证进程等待 我们知道fork函数可以创建一个子进程,而子进程通常是替父进程完成一些任务,而父进程在fork之后需要通过wait/waitpid等待子进程退出。这就是进程等待 进程等待的必要性 通过获…...
Docker学习(十八)load 和 import 命令的区别
Docker 中有两个命令可以将本地文件系统中的 tar 文件导入到 Docker 中:docker load 和 docker import。尽管它们的作用类似,但它们之间有一些重要的区别。 1.使用方式的不同: docker load 的使用示例: docker load --input tes…...
mysql中的事务
在日常生活中,我们会遇到一个场景,那就是在转账的时候,A有1000块钱,要给B转账500,那么最后的结果是A有500,B有500,但是也有可能出现A没有钱了,B有1000块,或者在转账过程中卡顿,这是不符合逻辑的,那么这个时候就要使用事务来解决问题 事务就是把一堆sql语句打包成一个整体,要么…...
《C++ Primer Plus》第18章:探讨 C++ 新标准(9)
编程练习 下面是一个简短程序的一部分: int main() {using namespace std;// list of double deduced from list contentsauto q average_list ({15.4, 10.7, 9.0});cout << q << endl;// list of int deduced from list contentscout << averag…...

记录一次PWM信号异常问题
问题我使用单片机输出PWM控制机械臂,但是控制过程中,机械臂总是会出现莫名的抽动。利用示波器测试PWM信号,发现信号正常。过程(1)在反复的测试过程中,队友提出,将示波器的地线放在左侧的GND波形…...
简单了解---性能测试
目录 一、什么是性能测试 二、常见的性能测试指标 1、并发 2、响应时间 3、事务 4、点击率 5、吞吐量 6、资源利用率 三、性能测试的分类 1、一般测试 2、负载测试 3、压力测试 4、稳定性测试 四、为什么要做性能测试? 五、影响性能的因素有哪些&…...

1.机器学习笔记第一周
机器学习利用领域: 1:随着网络数据增大,需要搜集用户的数据,做喜好性偏向判断等。 2:只要有数据的,无论是医疗领域,还是基因领域都是需要机器学习来发现数据密码。 3:机器自我学习…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...
vue3 vite.config.js 引入bem.scss文件报错
[sass] Can’t find stylesheet to import. ╷ 1 │ use “/bem.scss” as *; │ ^^^^^^^^^^^^^^^^^^^^^^ ╵ src\App.vue 1:1 root stylesheet 分析 我们遇到了一个在Vue3项目中使用Vite时,在vite.config.js中引入bem.scss文件报错的问题。错误信息指出在App.vue…...

Appium如何支持ios真机测试
ios模拟器上UI自动化测试 以appiumwebdriverio为例,详细介绍如何在模拟器上安装和测试app。在使用ios模拟器前,需要安装xcode,创建和启动一个simulator。simulator创建好后,就可以使用xcrun simctl命令安装被测应用并开始测试了。…...
Vue 3 Teleport 实战:优雅实现模态框、通知和全局组件
Vue 3 Teleport:突破 DOM 层级限制的组件渲染利器 在 Vue 应用开发中,组件通常与其模板的 DOM 结构紧密耦合。但当处理模态框(Modal)、通知(Toast)或全局 Loading 指示器时,这种耦合会成为障碍…...

zabbix 6 监控 docker 容器
zabbix 6 监控 docker 容器 1.安装zabbix_agent2 curl -s http://10.26.211.56:8080/centos7-agent2-install.sh | bash2.在zabbix server 端测试 zabbix_get -s 10.26.219.180 -k docker.infoZBX_NOTSUPPORTED: Cannot fetch data: Get "http://1.28/info": dial…...
【CSS-7】深入解析CSS伪类:从基础到高级应用
CSS伪类是前端开发中不可或缺的强大工具,它们允许我们根据文档树之外的信息或简单选择器无法表达的状态来样式化元素。本文将全面探讨CSS伪类的各种类型、使用场景和最佳实践。 1. 伪类基础概念 1.1 什么是伪类? 伪类(Pseudo-class&#x…...