哈希思想的应用

目录

1.位图

位图的实现

题目变形一

题目变形二

题目变形三

总结:

2.布隆过滤器

概念

布隆过滤器的实现

3.哈希切割的思想


1.位图

     哈希表和位图是数据结构中常用的两种技术。哈希表是一种数据结构,通过哈希函数把数据和位置进行映射,来实现快速的寻找、插入和删除操作。哈希表适用于海量数据处理,索引,数据压缩等方面有广泛应用123. 位图主要用于海量数据处理,索引,数据压缩等方面有广泛应用。位图的应用场景包括:

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

2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数。

如下题目:

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在
这40亿个数中。【腾讯】
位图解决
那么如何实现呢:
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一
个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0
代表不存在。
    首先40亿个整数大概需要4G*4的空间,16个g的空间,我们是无法开出这么大的空间,其次我们用数组访问,因此还是连续l6个g的空间,很明显,我们无法实现,那么如何来解决这个问题呢?
首先我们没必要把这么多数据存下来,我们只需要判断它在不在,而标记一个值在不在,最小的单位就是一个比特位,那么我们一个值映射一个比特位,就可以来表示这么多数据的存在情况。
此时我们只需要0.5G的空间即可,即42亿个比特位,此时0.5G就可以开出来了。

位图的实现

0.5G我们开不出bit类型的,我们只能开出整形或字符类型的。因此这里直接用vector来映射,因此我们需要计算出映射的位置。

如判断x是否存在,则我们需要计算x在第几个整形的第几个bit位上。

template<size_t N>class bitset
{
public:bitset(){_bit.resize(N/32);}void set(size_t x){size_t i = x / 32;//第几个整形size_t j = x % 32;//第几个位//找到该位置并置1 ,利用位运算计算//注意左移是向高位移,右移是向低位移_bit[i] |= (1 << j);//这里1左移再或上原数据,重新赋值后,该比特位就修改成1}void reset(size_t x){//与set相反,这里是将原来的x有存在变为不存在,不存在变为存在size_t i = x / 32;//第几个整形size_t j = x % 32;//第几个位//找到该位置//1变0   0变1_bit[i] &= ~(1 << j);}//检测是否中存在,即该位置是1还是0bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return _bit[i] & (1 << j);}
private://数据个数足够大,用16进制表示std::vector<int> _bit;size_t size;
};

题目变形一

给100亿个整数,找出其中出现一次的数。
/用两个数组表示两个bit位   
//用两位bit位映射一个数三种状态,存在,不存在,个数
//00 不存在  01存在   10两个以上的个数
template<size_t N>class twobitset
{
public:void set(const size_t x){if (bit1.test(x) == false && bit2.test(x) == false)//0 0 -> 0 1{bit2.set(x);}else if (bit1.test(x) == false && bit2.test(x) == true) //0 1 -> 1 0 {bit1.set(x);bit2.reset(x);}}
private:bitset<N> bit1;bitset<N> bit2;
};

题目变形二

给两个文件分别有100亿个整形数据,只有1G空间,找i出他们的交集。
解决方法:
各自映射到一个位图,两个位图如果都是存在,那么就是两者的交集的元素。

题目变形三

给定100亿个整数,1G内存,设计找到不查过2次的数据。
解决方案,用两个比特位表示四种状态:
00 不存在, 01存在,10有两个,11有三个以上。
template<size_t N>class twobitset
{
public:void set(const size_t x){if (bit1.test(x) == false && bit2.test(x) == false)//0 0 -> 0 1{bit2.set(x);}else if (bit1.test(x) == false && bit2.test(x) == true) //0 1 -> 1 0 {bit1.set(x);bit2.reset(x);}else if (bit1.test(x) == true && bit2.test(x) == false;)// 10 ->11{bit1.set(x);bit2.set(x);}}
private:bitset<N> bit1;bitset<N> bit2;
};

总结:

对于搜索:

1.暴力查找,数据量太大,效率太低。

2.排序+二分查找 ,极大的提升了效率。但还是存在不足:要排序。数组不方便增删。

3.引入搜索树,AVL树,红黑树。查找效率已经很可观了,但空间消耗较高。

4.哈希  ,与搜索树效率差不多,但对于大量搜索的整型数据,通过映射bit的思想实现更加高效,且节省空间。(但只能处理整形)

对于其他类型的,引出了布隆过滤器:

2.布隆过滤器

概念

布隆过滤器是一种概率型数据结构,用于判断一个元素是否在一个集合中。它可以节省空间和时间,但有一定的误判率:

1. 布隆过滤器的核心是一个位数组,即一个只包含0和1的数组,以及一组哈希函数,即一组可以将任意元素映射到位数组的索引的函数。

2. 当要添加一个元素时,先用哈希函数计算出它在位数组中的多个索引,然后将这些索引对应的值都设为1. 当要检查一个元素是否存在时,也先用哈希函数计算出它在位数组中的多个索引,然后检查这些索引对应的值是否都为1. 如果都为1,说明元素可能存在,如果有一个为0,说明元素一定不存在。

上述说了位图,我们知道位图可以来查找大量整形数据,但是对于其他类型,如字符型,就无法去查找,此时我们就需要有一种方法将他搞成整形。

直接用ascll码肯定不行,再通过哈希字符串算法转化一下,但是仍会有较大的冲突,还是有大概率的值是一样的,为了减少这些冲突,我们让一个字符串对应三个或者更多的哈希字符串算法转化后的整形,只有当这些整型值都存在的时候才存在,大大减少了重复带来的问题。各种字符串Hash函数 - clq - 博客园 (cnblogs.com)

但是还是存在问题:即使我们让一个字符串对应了三个转化后的数,但还是存在别的字符串也会对应这三个转化后的数(将不存在的判断为存在的),我们只能尽可能的减少这种情况,因此是否存在我们还是有不确定因素,但不存在我们一定能够能确定。

一个字符串对应的三个整数的对应比特位设置为1.

总的来说,存在误判率,但概率已经不是很大了。

那么如何选择n(插入元素个数)和k(映射的个数)的值呢?

有人给出了公式计算这里的m是布隆过滤器的长度。我们先以k=3先来实现。

布隆过滤器的实现

#pragma once
#include"bitset.h"
//这里我们就选用3个映射值来对应一个字符串,每一个映射值我们选取一种hash字符串算法
#include<string.h>
struct BKDR
{size_t operator()(const std::string& key){// BKDRsize_t hash = 0;for (auto e : key){hash *= 31;hash += e;}return hash;}
};
struct AP
{size_t operator()(const std::string& str){size_t hash = 0;int i = 0;char ch = str[i];for (auto ch: str){if ((i & 1) == 0){hash ^= ((hash << 7) ^ ch ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}i++;}return hash;}
};
struct SDB
{size_t operator()(const std::string& str){size_t hash = 0;for(auto ch:str){hash = 65599 * hash + ch;}return hash;}
};
template<size_t N,class K=std::string,class HashFunc1= BKDR,class HashFunc2 = AP,class HashFunc3 = SDB>
class BloomFilter
{
public://这里的类型就用泛型了void set(const K& key){//三个值来映射size_t hash1 = HashFunc1()(key) % N;size_t hash2 = HashFunc2()(key) % N;size_t hash3 = HashFunc3()(key) % N;_bit.set(hash1);_bit.set(hash2);_bit.set(hash3);}bool test(const K& key){size_t hash1 = HashFunc1()(key) % N;size_t hash2 = HashFunc2()(key) % N;size_t hash3 = HashFunc3()(key) % N;//只有当三个映射值都存在是才能表示存在if (_bit.test(hash1) == true&& _bit.test(hash2) == true&& _bit.test(hash3) == true){return true;//存在误判}return false;}/*double wrongrate(){return  }*/private://用位图封装bitset<N> _bit;
};

 事实上,空间开得越多,选用的映射值越多,都会之误判律极大地降低。

   对于布隆过滤器,一般是不支持删除的,我们在删除一个值这会影响以他的字符串成员存在变成不存在,如若像删除,就必须要引用计数,增加计数位(多个比特位),即对应的哈希值在每一次被set之后,对应的计数位++,判断是否存在时,同时添加计数位是否为零,其次删除后,就减减计数位的值,不过还是消耗了空间。

3.哈希切割的思想

​​​​​​​     哈希切割是一种将大文件分割成若干个小文件的方法,以便于处理海量数据。该方法使用哈希函数将相同的数据分配到同一个文件中。这种方法可以用于处理日志文件等大小超过100GB的文件

例题:

1. 给两个文件,分别有 100 亿个 query ,我们只有 1G 内存,如何找到两个文件交集?分别给出
精确算法和近似算法
解题思路:先将两个大文件各分割成新一个个小文件,之后两边的小文件分别比较,如何比较呢?
我们需要将100亿个query进行哈希切割,即把每一个query转化为整形在对其size取模,算出的值就是他对应的小文件。
变形2:
2.若是找出它出现次数前topk个query?如何查找
还是哈希切割思想,进行哈希切割,我们将字符串(query)利用哈希算法转化为整型,此时的值对应他的位置,而这里的位置就是对应的小文件,
小文件我们就可以直接用map或者unoderedmap来映射query的次数,之后再利用栈来记录次数最多的即可。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前缀和+哈希表——525. 连续数组

文章目录 ⛏1. 题目&#x1f5e1;2. 算法原理⚔解法一&#xff1a;暴力枚举⚔解法二&#xff1a;前缀和哈希表 ⚒3. 代码实现 ⛏1. 题目 题目链接&#xff1a;525. 连续数组 - 力扣&#xff08;LeetCode&#xff09; 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最…

SQL Server秘籍:数据分隔解密,数据库处理新境界!

点击上方蓝字关注我 在数据数据过程中经常会遇到数据按照一定字符进行拆分&#xff0c;而在不同版本的SQL SERVER数据库中由于包含的函数不同&#xff0c;处理的方式也不一样。本文将列举2个版本的数据库中不同的处理方法。 1. 使用 XML 方法 在SQL SERVER 2016版本之前&#x…

中东客户亲临广东育菁装备参观桌面型数控机床生产

近日&#xff0c;中东地区的一位重要客户在广东育菁装备有限公司的热情接待下&#xff0c;深入了解了该公司生产的桌面型数控机床。这次会面不仅加强了双方在业务领域的交流&#xff0c;也为中国与中东地区的经济合作描绘出更美好的前景。 在育菁装备公司各部门主要负责人及工作…

2018年2月26日 Go生态洞察:2017年Go用户调查结果分析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

手机技巧:安卓微信8.0.44测试版功能介绍

目录 一、更新介绍 二、功能更新介绍 拍一拍撤回功能 聊天设置界面文案优化 关怀模式新增了非常实用的安静模式 微信设置中新增翻译设置选项 近期腾讯官方终于发布了安卓微信8.0.44测试版&#xff0c;今天小编继续给大家介绍一个本次安卓微信8.0.44测试版本更新的内容&am…

《大话设计模式》(持续更新中)

《大话设计模式》 序 为什么要学设计模式第0章 面向对象基础什么是对象&#xff1f;什么是类&#xff1f;什么是构造方法&#xff1f;什么是重载&#xff1f;属性与字段有什么区别&#xff1f;什么是封装&#xff1f;什么是继承&#xff1f;什么是多态&#xff1f;抽象类的目的…

字符串原地旋转

记录一下做的练习题 字符串原地旋转&#xff1a;五 三 mat [[1,2,3],[3,4,5],[4,5,6]] tag0 total 0 for i in mat:total total i[tag]tag 1 print(total) 四 X [[12,7,3],[4,5,6],[7,8,9]] Y [[5,8,1],[6,7,3],[4,5,9]] res [[0,0,0],[0,0,0],[0,0,0]] for i in rang…

如何快速搭建一个大模型?简单的UI实现

&#x1f525;博客主页&#xff1a;真的睡不醒 &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;相信自己&#xff0c;一路风景一路歌&#xff0c;人生之美&#xff0c;正在于…

makefile编写练习

makefile编写练习 OVERVIEW makefile编写练习文件结构直接编译整个项目并运行将项目制作成为静态库将项目制作成为动态库 编写makefile文件来编译带头文件的程序&#xff0c; 文件结构 初始项目文件结构&#xff0c;如下所示&#xff1a; #ifndef ADD_HPP #define ADD_HPPint…

乘波前行的问题

1.问题&#xff1a; 考虑两个信号叠加在一起&#xff0c;比如&#xff0c;一个是工频信号50Hz&#xff0c;一个是叠加的高频信号比如有3KHz&#xff0c;简单起见&#xff0c;两个信号都是幅值固定的标准的正弦波&#xff0c;现在我们期望得到那个高频信号&#xff0c;相对工频…

Royal TSX v6.0.1

Royal TSX是一款基于插件的软件&#xff0c;适用于Windows系统&#xff0c;可以用于远程连接和管理服务器。它支持多种连接类型&#xff0c;如RDP、VNC、基于SSH连接的终端&#xff0c;SFTP/FTP/SCP或基于Web的连接管理。 在安装Royal TSX后&#xff0c;需要进行一些基础配置&…

2023人形机器人行业海外科技研究:从谷歌看机器人大模型进展

今天分享的是人形机器人系列深度研究报告&#xff1a;《2023人形机器人行业海外科技研究&#xff1a;从谷歌看机器人大模型进展》。 &#xff08;报告出品方&#xff1a;华鑫证券&#xff09; 报告共计&#xff1a;26页 大模型是人形机器人的必备要素 长期来看&#xff0c;人…

openEuler 22.03 LTS x86_64 cephadm 部署ceph 16.2.14 未完成 笔记

环境 准备三台虚拟机 10.47.76.94 node-1 10.47.76.95 node-2 10.47.76.96 node-3 下载cephadm [rootnode-1 ~]# yum install cephadm Last metadata expiration check: 0:11:31 ago on Tue 21 Nov 2023 10:00:20 AM CST. Dependencies resolved. Package …

数据结构(超详细讲解!!)第二十五节 线索二叉树

1.线索二叉树的定义和结构 问题的提出&#xff1a; 通过遍历二叉树可得到结点的一个线性序列&#xff0c;在线性序列中&#xff0c;很容易求得某个结点的直接前驱和后继。但是在二叉树上只能找到结点的左孩子、右孩子&#xff0c;结点的前驱和后继只有在遍历过程中才能得到…

Alfred v5.1.4(mac快速启动)

Mac效率办公软件哪个好&#xff1f;Alfred是一款Mac电脑上的快速启动和工作流自动化工具&#xff0c;它可以帮助用户快速访问文件、应用程序、web搜索和系统工具&#xff0c;提高工作效率。以下是Alfred的特点&#xff1a; 快速启动&#xff1a;用户可以通过Alfred快速启动应用…

Node.js入门指南(四)

目录 express框架 express介绍 express使用 express路由 express 响应设置 中间件 路由模块化 EJS 模板引擎 express-generator hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识&#xff0c;这篇文章主要给大家分享Nod…

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都…

(2023码蹄杯)省赛(初赛)第三场真题(原题)(题解+AC代码)

题目1&#xff1a;MC0227堆煤球 码题集OJ-堆煤球 (matiji.net) 思路&#xff1a; 1.i从l枚举到r,i是8的倍数就跳过&#xff0c;i不是8的倍数就用等差数列求和公式i(1i)/2,最后累加到答案中即可 AC_Code:C #include<bits/stdc.h> using namespace std;int main( ) {in…

轻松实现文件按数量平均分类,高效整理并自动新建文件夹保存“

你是否曾经因为文件数量过多&#xff0c;整理起来繁琐而感到烦恼&#xff1f;是否曾经为了新建文件夹而手动一个一个进行创建&#xff0c;费时又费力&#xff1f;现在&#xff0c;我们的智能文件管理工具将为你解决这些问题&#xff01; 首先第一步&#xff0c;我们要进入文件…

【开源】基于Vue.js的网上药店系统

项目编号&#xff1a; S 062 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S062&#xff0c;文末获取源码。} 项目编号&#xff1a;S062&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 药品类型模块2.3 药…