[C++ ]21:哈希+海量数据处理

[C++ ]21:哈希+海量数据处理

  • 一.哈希:
    • 1.位图:
      • 1.题目一:
        • 方法一:
        • 方法二:
      • 2.题目二:
        • 方法一:
        • 补充:
      • 3.题目三:
        • 方法一:双位图
      • 4.题目四:
  • 二.布隆过滤器:
    • 1.基本概念:
    • 2.基本结构:
    • 3.为什么存在误判?
    • 4.如何减少误判?
    • 5.布隆过滤器如何支持删除操作?
    • 6.应用:
      • 应用:
      • 题目一:
        • 精确算法(哈希切割):
        • 特殊情况:哈希切分本质不平均切分!
        • 近似算法(布隆过滤器):
  • 三.海量数据处理:
    • 1.哈希切割:
      • 题目一:
        • 方法一:哈希切分+map
        • 方法二:大堆解决

一.哈希:

1.位图:

1.题目一:

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

方法一:

1.排序+二分方法
2.时间复杂度:n*logn + logn
3.空间复杂度O(n)

1.40亿的不重复整数使用上面的方法需要保存在数组中。
2.40亿数有160亿字节的数据计算大概是14.9g
3.说明我们需要14.9g的内存给这个程序才可以在数组中存放足够的数据。
4.保存到数组中进行排序+二分。

方法二:

1.非常明显上面的方法是不靠谱的需要大量的内存+时间才可以找到数据。
2.题目要求只需要判断数据在不在。
3.使用哈希位图的方法1为存在0为不存在。
4.位置和值进行一一对应。

1.每一个方块是4个字节,4个字节4个字节开比较方便。
2.从第一个整形开始计数第几个位表示数值几。
3.使用除和模的方法获取当前需要存放的数据和判断数据的位置。
4.原来4个字节存一个数据现在存32个数据。
5.数据大概不到0.5个g就可以保存。

在这里插入图片描述

template<size_t N>
class Hashset {
public:Hashset(){//40亿无符号整数_N.resize(N/32 + 1 , 0);}//1.设置:void set(size_t n){int i = n / 32;int j = n % 32;_N[i] |= (1 << j);}//2.消除:void reset(size_t n){int i = n / 32;int j = n % 32;_N[i] &=(~(1 << j));}//3.查找!bool find(size_t n){int i = n / 32;int j = n % 32;return (1 << j) & _N[i];}private:vector<int> _N;
};

1.创建一个哈希位图使用整形开空间。
2.使用模板的特化传N是开多少个整形空间的大小。
3.使用set和reset放置数据和去除数据。
4.使用find判断数据是否存在1为存在0为不存在。
5.补充:<< 位向高位移动低位补0. >> 位向高位移动低位补0

2.题目二:

方法一:

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

1,题目需要记录出现的次数我们可以使用两个位图保存数据出现的次数情况。
2.00 没有出现 01出现一次 10表示出现两次 11表示出现三次和以上。
3.100亿个整数只需要开数据大小范围的位图就可以。
4.2^32范围的整数,100亿数据一定存在有一些数据重复出现的情况。

#include"Hashset.h"template<size_t N>
class Double_set {
public://1.++void set_add(size_t n){int a = _prev.find(n);int b = _next.find(n);if (b == 0 && a == 0){_next.set(n);}else if (b == 1 && a == 0){_next.reset(n);_prev.set(n);}else if (b == 0 && a == 1){_next.set(n);}}//2.判断出现一次的个数:bool pwd(size_t n){int a = _prev.find(n);int b = _next.find(n);if (a == 0 && b == 1)return true;return false;}
private:Hashset<N> _prev;Hashset<N> _next;
};
//2.100亿重复数据判断出现一次:
void exam_2()
{Double_set<40> h2;vector<size_t> arr = { 1,1,2,2,3,4,4,4,5,6,6,7,9,9,9,9,10 };for (auto& e : arr){h2.set_add(e);}for (int j = 0; j < 11; j++){if (h2.pwd(j))cout << j << "出现一次" << endl;elsecout << j << "出现次数不是一次" << endl;}
}
补充:

在这里插入图片描述

3.题目三:

给两个文件,分别有100亿个整数数据,我们只有1G内存我们需要找到两个文件的交集。

方法一:双位图

1,46亿多个数据,需要不到0.5个g
2.分别使用位图保存数据1表示数据在0表示数据不在。
3.两个文件分别使用位图进行保存

void exam_3()
{Hashset<-1> h1;Hashset<-1> h2;srand(time(NULL));for (size_t i=0 ; i< 42949; i++){size_t n = (rand()+i) % 42949;h1.set(n);}for (size_t i = 0; i < 42949; i++){size_t n = (rand() + i) % 42949;h2.set(n);}for (int i = 0; i < 42949; i++){int a = h1.find(i);int b = h2.find(i);if (a == 1 && b == 1)cout << i << "是两个文件的交集" << endl;}
}

1.两个文件分别放入两个set中,然后每一个位进行数据比较。
2.上面的这个操作是默认去重的,因为存放数据只存放一个。
3.如果不想要去重操作,可以set一个文件到位图中,然后使用另一个文件遍历第一个位图就可以找到重复数据的交集。

4.题目四:

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

1,题目需要记录出现的次数我们可以使用两个位图保存数据出现的次数情况。
2.00 没有出现 01出现一次 10表示出现两次 11表示出现三次和以上。
3.100亿个整数只需要开数据大小范围的位图就可以。
4.2^32范围的整数,100亿数据一定存在有一些数据重复出现的情况。
5.int数据的范围是 -2147483648 2147483647 int中会出现负数,负数对应不了下标位置需要int转size_t类型的数据。

template<size_t N>
class Double_set_3 {
public://1.++void set_add(size_t n){int a = _prev.find(n);int b = _next.find(n);if (b == 0 && a == 0){_next.set(n);}else if (b == 1 && a == 0){_next.reset(n);_prev.set(n);}else if (b == 0 && a == 1){_next.set(n);}}//2.判断出现一次的个数:bool pwd(size_t n){int a = _prev.find(n);int b = _next.find(n);//如果出现次数至少为三次就返回假。if (a == 1 && b == 1)return false;return true;}
private:Hashset<N> _prev;Hashset<N> _next;
};
void exam_4()
{Double_set_3<200> h1;vector<int> arr = { 1,1,2,2,2,3,3,3,4,4,5,6,6,7,7,7,7,8,8,8,8,9,10 };for (auto& e : arr){h1.set_add(e);}for (int i = 0; i < 200; i++){if (h1.pwd(i))cout << i << "出现次数不超过两次" << endl;}
}

//1.vector中存放的数据类型是int
//2.数据量和可以出现的数据访问过于悬殊导致位图基本上就是1 1 的结构
//3.作为size_t 类型是4294967295 作为int 类型是-1!

二.布隆过滤器:

1.基本概念:

在这里插入图片描述

一对一是处理不了字符串的问题非常容易产生了哈希冲突,需要布隆过滤器的存在!

1.普通的位图只能处理整形和无符号整形的问题根据位置确定数据值。
2.布隆过滤器=哈希+位图
3.把字符串进行转化==(不同的哈希函数)==存放在位图的多个位置,一个字符串映射多个位置。
4.开位图空间要多开一些?比如有100字符串一个字符串映射多个位,开的位图空间需要足够大。

2.基本结构:

struct HashFuncBKDR
{// BKDRsize_t operator()(const string& s){size_t hash = 0;for (auto ch : s){hash *= 131;hash += ch;}return hash;}
};struct HashFuncAP
{// APsize_t operator()(const string& s){size_t hash = 0;for (size_t i = 0; i < s.size(); i++){if ((i & 1) == 0) // żÊýλ×Ö·û{hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));}else              // ÆæÊýλ×Ö·û{hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));}}return hash;}
};struct HashFuncDJB
{// DJBsize_t operator()(const string& s){size_t hash = 5381;for (auto ch : s){hash = hash * 33 ^ ch;}return hash;}
};template<size_t N, class T = string,class Hash_1 = HashFuncBKDR,class Hash_2 = HashFuncAP,class Hash_3 = HashFuncDJB
>
class Blond_1 {
public://1.放置:void set(const T& x){//需要三个不同的哈希函数计算出3个不同的映射位置:size_t a = Hash_1()(x)%M;size_t b = Hash_2()(x)%M;size_t c = Hash_3()(x)%M;_h.set(a);_h.set(b);_h.set(c);}//2.判断数据存在的问题!bool test(const T& x){//1.映射的三个位置有一个为0这个数据都不存在(一定)size_t a = Hash_1()(x) % M;if (!_h.find(a))return false;size_t b = Hash_2()(x) % M;if (!_h.find(b))return false;size_t c = Hash_3()(x) % M;if (!_h.find(c))return false;//2.映射的三个位置都存在一定存在吗?(不确定的:存在误判!)return true;}private:static const size_t M = N * 10;//一个字符串会去映射多个位*10 空间大小Hashset<M> _h;//类的静态成员不在对象中开空间
};

如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1,例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7,则上图转变为:

3.为什么存在误判?

在这里插入图片描述

void exam_1()
{Blond_1<10> b1;string s1("百度");string s2("字节");string s3("网易");b1.set(s1);b1.set(s2);b1.set(s3);vector<string> v1 = { "百度","字节","网易","腾讯"};for (auto& e : v1){if (b1.test(e))cout << e << "可能存在" << endl;elsecout << e << "一定不存在" << endl;}
}

1.我们把百度,字节,网易,每个字符串哈希映射到位图的三个位置(如下图所示)
2.当我们判断腾讯在不在的时候会出现误判:
3.腾讯不存在位图中,通过三个哈希函数可以计算到三个位置并且这三个位置都被百度,字节,网易中的一个所占有,产生了误判!(实际不产生误判!数据量较小)

在这里插入图片描述

4.如何减少误判?

如何选择哈希函数个数和布隆过滤器长度
很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

请添加图片描述
在这里插入图片描述
在这里插入图片描述

1.增加布隆过滤器的长度,提高长度/数据量的比值。
2.增加哈希函数的个数,但是考虑映射速度和空间大小的问题。
2-1:哈希函数越多,整个位图变1的速度越快。
2-2:哈希函数越多,整个位图空间的消耗变快。
3.哈希函数变少也会导致误报率变高。

5.布隆过滤器如何支持删除操作?

1.增加引用计数可以解决删除的问题。
2.一个位置可能被重复多次的被设置,如果没有引用记数操作那么可能一次删除就影响到其他字符串的存在。
3.增加一个位图块的大小到8bit。
4.可以使用8bit的第一个保存是否存在,剩下七个去保存引用计数的次数。

在这里插入图片描述

6.应用:

应用:

1.注册用户名重复的判断。
2.布隆过滤器存在哈希冲突,数据库的访问查找是确定性的。
3.如果不在布隆过滤器中就一定不是重复的用户名称。
4.在前端和数据库中加上一个布隆过滤器可以降低数据库的访问需求。
5.数据库的数据查询是基于网络的,布隆过滤器是基于本地的快速判断。

在这里插入图片描述

题目一:

给两个文件分别有100亿的字符串,我们只有1G内存怎么找到两个文件的交集?

精确算法(哈希切割):

1.假设一个字符串的大小是50byte
2.100亿个字符串是多少G —>5千亿字节—>500G (1g大概为10亿字节)
3.我们只有1G内存两个文件可以考虑不平均切分为1000份!

在这里插入图片描述

问题:两个文件需要找交集切分出来的两块A0 和 B0 怎么保证是对应类型的字符串?
哈希切分:
1.当前是A0 和 B0 分别放在问题中去找交集。
2.如何确定A中的那些文件放在A0,B中的那些文件放在B0?
3.使用哈希函数i = HashFunc(queue)%1000;
4.i就是Ai或者Bi

特殊情况:哈希切分本质不平均切分!

存在一个Ai 或者 Bi 过大的情况?
解决方法一:进入递归的哈希切分。
解决方法二:可以在同一个位置出现的字符串,是相同的字符串或者相似字符串。考虑把这些字符串放到位图中先进行去重操作再放到setA和setB中(解决重复数据较多的情况)
解决方法三:哈希冲突多—>导致的文件过大?可以调整哈希切分函数–>进行二次切分。

近似算法(布隆过滤器):

思路:
1.把一个文件的字符串放到布隆过滤器中。
2.遍历另一个文件,另一个文件中的字符串每一个都去判断一下在不在布隆过滤器中。
3.因为存在哈希冲突有可能有一些数据不是交集但是在布隆过滤器中出现存在这个就是哈希冲突。
4.综上所述:近似的算法。

三.海量数据处理:

1.哈希切割:

题目一:

给一个超过100G大小的log file , log中存ip,设计算法找到出现次数最多的IP,转化为找topk ip问题。

方法一:哈希切分+map

在这里插入图片描述

方法二:大堆解决

1.定义一个pair<string , int> 类型的结构保存在堆中。
2.堆不会存在有重复的数据节点。
3.插入一个pair<string , int> string已经在堆中存在就++int类型的值。
4.插入一个pair<string , int> string之前没有在堆中存在就正常插入pair到堆中。
5.通过pait<string , int> 比较使用仿函数调int这个数据去比较。

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

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

相关文章

k8s的pod访问service的方式

背景 在k8s中容器访问某个service服务时有两种方式&#xff0c;一种是把每个要访问的service的ip注入到客户端pod的环境变量中&#xff0c;另一种是客户端pod先通过DNS服务器查找对应service的ip地址&#xff0c;然后在通过这个service ip地址访问对应的service服务 pod客户端…

如何使用Java语言发票查验接口实现发票真伪查验、票据ocr

随着时代潮流的发展&#xff0c;企业也在寻找更加便捷、高效的办公模式&#xff0c;尤其是针对财务工作人员而言&#xff0c;繁琐的发票录入、查验工作占据了财务人员的大部分时间。对此&#xff0c;翔云提供了发票识别接口、发票查验接口&#xff0c;那么企业应当如何将这些接…

数据结构算法题(力扣)——链表

以下题目建议大家先自己动手练习&#xff0c;再看题解代码。这里只提供一种做法&#xff0c;可能不是最优解。 1. 移除链表元素&#xff08;OJ链接&#xff09; 题目描述&#xff1a;给一个链表的头节点 head 和一个整数 val &#xff0c;删除链表中所有满足值等于 val 的节点…

【 书生·浦语大模型实战营】学习笔记(一):全链路开源体系介绍

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

linux 回收站机制(笔记)

Linux下回收站机制https://mp.weixin.qq.com/s/H5Y8VRcaOhFZFXzR8yQ7yg 功能 &#xff1a;设立回收站&#xff0c;并且可定时清空回收站。 一、建议将alias rm 改成别的。 比如alias rmm &#xff0c;同时修改rm -rf ~/.trash/* 改成 rmm -rf ~/.trash/* 不然影响rm 的正常使…

js 基础知识 forEach 和 map 的区别,及 map 不加 return 返回什么

问题一&#xff1a;forEach 和 map 之间的区别&#xff1a; 1、forEach 不返回新数组&#xff0c;map 返回新数组&#xff0c;其中包含回调函数的返回值。 2、用途&#xff1a;如果只想要遍历数组并对每个元素执行某些操作而不产生新数组&#xff0c;那么应该使用 forEach&am…

从零开始学RSA加密解密过程

因为文字太过晦涩难懂&#xff0c;下面以图示的方法来理解RSA加密解密的过程 以上过程中因为HACK无法得到p,q信息&#xff0c;也就是无法计算出d , 导致了无法解密 c 得到 m (n,e) 公钥 (d,n) 私钥 (p,q,n,e) 生成的加密必要信息 必要的公式 c ≡ me mod n ----------->…

基于栈结构的非递归二叉树结点关键字输出算法

基于栈结构的非递归二叉树结点关键字输出算法 一、引言二、二叉树基本概念三、非递归遍历算法基础四、算法设计五、算法实现六、C代码示例七、算法分析八、优化与讨论 一、引言 在计算机科学中&#xff0c;二叉树是一种重要的数据结构&#xff0c;它广泛应用于各种算法和数据结…

Hive函数笔试题(简单)

第1题 有如下的用户访问数据 userId visitDate visitCount u01 2017/1/21 5 u02 2017/1/23 6 u03 2017/1/22 8 u04 2017/1/20 3 u01 2017/1/23 6 u01 2017/2/21 8 u02 2017/1/23 6 u01 2017/2/22 4 要求使用SQL统计出每个用户的累积访问次数&…

【方案篇】事件监听函数的内存泄漏,帮你搞定!

本文是 理论篇 &#xff0c;还有下篇 代码篇。 前言 工作中&#xff0c;我们会对window, DOM节点&#xff0c;WebSoket, 或者单纯的事件中心等注册事件监听函数。 // window window.addEventListener("message", this.onMessage); // WebSoket socket.addEventLis…

大数据学习第十一天(复习linux指令3)

1、su和exit su命令就是用于账户切换的系统命令 基本语法&#xff1a;su[-] [用户名] 1&#xff09;-表示是否在切换用户后加载变量&#xff0c;建议带上 2&#xff09;参数&#xff1a;用户名&#xff0c;表示切换用户 3&#xff09;切换用户后&#xff0c;可以通过exit命令退…

Spring定义Bean对象笔记(二)

前言&#xff1a;上一篇记录了通过XML文件来定义Bean对象&#xff0c;这一篇将记录通过注解和配置类的方式来定义Bean对象。 核心注解&#xff1a; 定义对象&#xff1a;Component,Service,Repository,Controller 依赖注入&#xff1a; 按类型&#xff1a;Autowired 按名称&am…

【Unity每日一记】(Canvas的相机渲染模式) 如何将模型显示在UI之前

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

Stable Diffusion扩散模型推导公式的基础知识

文章目录 1、独立事件的条件概率2、贝叶斯公式、先验概率、后验概率、似然、证据3、马尔可夫链4、正态分布 / 高斯分布5、重参数化技巧6、期望7、KL散度 、高斯分布的KL散度8、极大似然估计9、ELBO :Evidence Lower Bound10、一元二次方程 1、独立事件的条件概率 A 和 B 是两个…

Java编程使用CGLIB动态代理介绍与实战演示

文章目录 前言技术积累核心概念主要功能适用场景与JDK动态代理的对比 实战演示定义待代理的目标类实现MethodInterceptor接口使用代理对象 测试结果写在最后 前言 在Java编程中&#xff0c;CGLIB (Code Generation Library) 是一个强大的高性能代码生成库&#xff0c;它通过生…

2024年第三期丨全国高校大数据与人工智能师资研修班邀请函

2024年第三期 杭州线下班 数据采集与机器学习实战&#xff08;Python&#xff09; 线上班 八大专题 大模型技术与应用实战 数据采集与处理实战&#xff08;Python&八爪鱼&#xff09; 大数据分析与机器学习实战&#xff08;Python&#xff09; 商务数据分析实战&…

jQuery(一)

文章目录 1. 基本介绍2.原理示意图3.快速入门1.下载jQuery2.创建文件夹&#xff0c;放入jQuery3.引入jQuery4.代码实例 4.jQuery对象与DOM对象转换1.基本介绍2.dom对象转换JQuery对象3.JQuery对象转换dom对象4.jQuery对象获取数据获取value使用val&#xff08;&#xff09;获取…

完全没想到docker启动败在了这里!

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 故事背景 前几天帮同事部署一个环境&#xff0c;用他写的安装脚本部署&#xff0c;其中一台服务器就需要安装docker&#xff0c…

基于深度学习的铁轨缺陷检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要&#xff1a;本文深入研究了基于YOLOv8/v7/v6/v5的铁轨缺陷检测系统。核心技术上&#xff0c;文章采用了最先进的YOLOv8&#xff0c;并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;进行了性能指标的对比分析。文中详细阐述了国内外铁轨缺陷检测的研究现状、数据集处理方法…

MHA高可用-解决MySQL主从复制的单点问题

目录 一、MHA的介绍 1&#xff0e;什么是 MHA 2&#xff0e;MHA 的组成 2.1 MHA Node&#xff08;数据节点&#xff09; 2.2 MHA Manager&#xff08;管理节点&#xff09; 3&#xff0e;MHA 的特点 4. MHA工作原理总结如下&#xff1a; 二、搭建 MySQL MHA 实验环境 …